Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance improvements #114

Merged
merged 8 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions theseus/src/api/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ pub async fn get_forge_versions() -> crate::Result<Manifest> {

Ok(tags)
}

#[tracing::instrument]
pub async fn get_quilt_versions() -> crate::Result<Manifest> {
let state = State::get().await?;
let tags = state.metadata.read().await.quilt.clone();

Ok(tags)
}
3 changes: 2 additions & 1 deletion theseus/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ pub mod tags;
pub mod data {
pub use crate::state::{
DirectoryInfo, Hooks, JavaSettings, MemorySettings, ModLoader,
ProfileMetadata, Settings, Theme, WindowSize,
ModrinthProject, ModrinthTeamMember, ModrinthUser, ModrinthVersion,
ProfileMetadata, ProjectMetadata, Settings, Theme, WindowSize,
};
}

Expand Down
142 changes: 70 additions & 72 deletions theseus/src/api/pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::event::emit::{
};
use crate::event::{LoadingBarId, LoadingBarType};
use crate::state::{
LinkedData, ModrinthProject, ModrinthVersion, ProfileInstallStage, SideType,
LinkedData, ModrinthProject, ModrinthVersion, Profile, ProfileInstallStage,
SideType,
};
use crate::util::fetch::{
fetch, fetch_advanced, fetch_json, fetch_mirrors, write, write_cached_icon,
Expand Down Expand Up @@ -325,6 +326,7 @@ async fn install_pack(
prof.metadata.icon = icon.clone();
prof.metadata.game_version = game_version.clone();
prof.metadata.loader_version = loader_version.clone();
prof.metadata.loader = mod_loader.unwrap_or(ModLoader::Vanilla);

async { Ok(()) }
})
Expand Down Expand Up @@ -409,83 +411,79 @@ async fn install_pack(
)
.await?;

let extract_overrides = |overrides: String| async {
let reader = Cursor::new(&file);

let mut overrides_zip =
ZipFileReader::new(reader).await.map_err(|_| {
crate::Error::from(crate::ErrorKind::InputError(
"Failed extract overrides Zip".to_string(),
))
})?;

let profile = profile.clone();
async move {
for index in 0..overrides_zip.file().entries().len() {
let file = overrides_zip
.file()
.entries()
.get(index)
.unwrap()
.entry()
.clone();

let file_path = PathBuf::from(file.filename());
if file.filename().starts_with(&overrides)
&& !file.filename().ends_with('/')
{
// Reads the file into the 'content' variable
let mut content = Vec::new();
let mut reader =
overrides_zip.entry(index).await?;
reader
.read_to_end_checked(&mut content, &file)
.await?;

let mut new_path = PathBuf::new();
let components = file_path.components().skip(1);

for component in components {
new_path.push(component);
}
emit_loading(&loading_bar, 0.0, Some("Extracting overrides"))
.await?;

if new_path.file_name().is_some() {
write(
&profile.join(new_path),
&content,
&state.io_semaphore,
)
.await?;
}
}
}
let mut total_len = 0;

Ok::<(), crate::Error>(())
for index in 0..zip_reader.file().entries().len() {
let file =
zip_reader.file().entries().get(index).unwrap().entry();

if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
total_len += 1;
}
.await
};
}

emit_loading(&loading_bar, 0.0, Some("Extracting overrides"))
.await?;
extract_overrides("overrides".to_string()).await?;
extract_overrides("client_overrides".to_string()).await?;
emit_loading(
&loading_bar,
29.9,
Some("Done extracting overrides"),
)
.await?;
for index in 0..zip_reader.file().entries().len() {
let file = zip_reader
.file()
.entries()
.get(index)
.unwrap()
.entry()
.clone();

let file_path = PathBuf::from(file.filename());
if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
// Reads the file into the 'content' variable
let mut content = Vec::new();
let mut reader = zip_reader.entry(index).await?;
reader.read_to_end_checked(&mut content, &file).await?;

let mut new_path = PathBuf::new();
let components = file_path.components().skip(1);

for component in components {
new_path.push(component);
}

if new_path.file_name().is_some() {
write(
&profile.join(new_path),
&content,
&state.io_semaphore,
)
.await?;
}

if let Some(profile) =
crate::api::profile::get(&profile).await?
emit_loading(
&loading_bar,
30.0 / total_len as f64,
Some(&format!(
"Extracting override {}/{}",
index, total_len
)),
)
.await?;
}
}

if let Some(profile_val) =
crate::api::profile::get(&profile, None).await?
{
tokio::try_join!(
super::profile::sync(&profile.path),
crate::launcher::install_minecraft(
&profile,
Some(loading_bar)
),
)?;
Profile::sync_projects_task(profile.clone());
crate::launcher::install_minecraft(
&profile_val,
Some(loading_bar),
)
.await?;
}

Ok::<PathBuf, crate::Error>(profile.clone())
Expand Down
37 changes: 30 additions & 7 deletions theseus/src/api/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub use crate::{
state::{JavaSettings, Profile},
State,
};
use std::collections::HashMap;
use std::{
future::Future,
path::{Path, PathBuf},
Expand Down Expand Up @@ -40,11 +41,21 @@ pub async fn remove(path: &Path) -> crate::Result<()> {

/// Get a profile by path,
#[tracing::instrument]
pub async fn get(path: &Path) -> crate::Result<Option<Profile>> {
pub async fn get(
path: &Path,
clear_projects: Option<bool>,
) -> crate::Result<Option<Profile>> {
let state = State::get().await?;
let profiles = state.profiles.read().await;
let mut profile = profiles.0.get(path).cloned();

if clear_projects.unwrap_or(false) {
if let Some(profile) = &mut profile {
profile.projects = HashMap::new();
}
}

Ok(profiles.0.get(path).cloned())
Ok(profile)
}

/// Edit a profile using a given asynchronous closure
Expand Down Expand Up @@ -79,11 +90,23 @@ where

/// Get a copy of the profile set
#[tracing::instrument]
pub async fn list() -> crate::Result<std::collections::HashMap<PathBuf, Profile>>
{
pub async fn list(
clear_projects: Option<bool>,
) -> crate::Result<HashMap<PathBuf, Profile>> {
let state = State::get().await?;
let profiles = state.profiles.read().await;
Ok(profiles.0.clone())
Ok(profiles
.0
.clone()
.into_iter()
.map(|mut x| {
if clear_projects.unwrap_or(false) {
x.1.projects = HashMap::new();
}

x
})
.collect())
}

/// Query + sync profile's projects with the UI from the FS
Expand Down Expand Up @@ -117,7 +140,7 @@ pub async fn sync(path: &Path) -> crate::Result<()> {
/// Installs/Repairs a profile
#[tracing::instrument]
pub async fn install(path: &Path) -> crate::Result<()> {
let profile = get(path).await?;
let profile = get(path, None).await?;

if let Some(profile) = profile {
crate::launcher::install_minecraft(&profile, None).await?;
Expand Down Expand Up @@ -398,7 +421,7 @@ pub async fn run_credentials(
let state = State::get().await?;
let settings = state.settings.read().await;
let metadata = state.metadata.read().await;
let profile = get(path).await?.ok_or_else(|| {
let profile = get(path, None).await?.ok_or_else(|| {
crate::ErrorKind::OtherError(format!(
"Tried to run a nonexistent or unloaded profile at path {}!",
path.display()
Expand Down
2 changes: 2 additions & 0 deletions theseus/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ impl Drop for LoadingBar {
let loader_uuid = self.loading_bar_uuid;
let event = self.bar_type.clone();
let fraction = self.current / self.total;

#[cfg(feature = "cli")]
let cli_progress_bar = self.cli_progress_bar.clone();

tokio::spawn(async move {
Expand Down
24 changes: 12 additions & 12 deletions theseus/src/launcher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ pub async fn install_minecraft(
existing_loading_bar: Option<LoadingBarId>,
) -> crate::Result<()> {
Box::pin(async move {
let loading_bar = init_or_edit_loading(
existing_loading_bar,
LoadingBarType::MinecraftDownload {
// If we are downloading minecraft for a profile, provide its name and uuid
profile_name: profile.metadata.name.clone(),
profile_path: profile.path.clone(),
},
100.0,
"Downloading Minecraft",
)
.await?;

crate::api::profile::edit(&profile.path, |prof| {
prof.install_stage = ProfileInstallStage::Installing;

Expand Down Expand Up @@ -90,18 +102,6 @@ pub async fn install_minecraft(
format!("{}-{}", version.id.clone(), it.id.clone())
});

let loading_bar = init_or_edit_loading(
existing_loading_bar,
LoadingBarType::MinecraftDownload {
// If we are downloading minecraft for a profile, provide its name and uuid
profile_name: profile.metadata.name.clone(),
profile_path: profile.path.clone(),
},
100.0,
"Downloading Minecraft",
)
.await?;

// Download version info (5)
let mut version_info = download::download_version_info(
&state,
Expand Down
8 changes: 5 additions & 3 deletions theseus/src/state/children.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,11 @@ impl Children {
let child = child.clone();
let child = child.write().await;
if child.current_child.write().await.try_wait()?.is_none() {
if let Some(prof) =
crate::api::profile::get(&child.profile_path.clone())
.await?
if let Some(prof) = crate::api::profile::get(
&child.profile_path.clone(),
None,
)
.await?
{
profiles.push(prof);
}
Expand Down
2 changes: 1 addition & 1 deletion theseus/src/state/profiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ impl Profile {
tokio::task::spawn(async move {
let res = async {
let state = State::get().await?;
let profile = crate::api::profile::get(&path).await?;
let profile = crate::api::profile::get(&path, None).await?;

if let Some(profile) = profile {
let paths = profile.get_profile_project_paths()?;
Expand Down
2 changes: 1 addition & 1 deletion theseus_cli/src/subcommands/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ impl ProfileList {
_args: &crate::Args,
_largs: &ProfileCommand,
) -> Result<()> {
let profiles = profile::list().await?;
let profiles = profile::list(None).await?;
let rows = profiles.values().map(ProfileRow::from);

let table = table(rows).with(
Expand Down
2 changes: 1 addition & 1 deletion theseus_gui/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ tauri-build = { version = "1.2", features = [] }
regex = "1.5"

[dependencies]
theseus = { path = "../../theseus", features = ["tauri", "cli"] }
theseus = { path = "../../theseus", features = ["tauri"] }

serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion theseus_gui/src-tauri/src/api/jre.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub async fn jre_get_optimal_jre_key(profile: Profile) -> Result<String> {
// The key can be used in the hashmap contained by JavaGlobals in Settings (if it exists)
#[tauri::command]
pub async fn jre_get_optimal_jre_key_by_path(path: &Path) -> Result<String> {
let profile = profile::get(path).await?.ok_or_else(|| {
let profile = profile::get(path, Some(true)).await?.ok_or_else(|| {
TheseusSerializableError::NoProfileFound(path.display().to_string())
})?;
Ok(jre::get_optimal_jre_key(&profile).await?)
Expand Down
6 changes: 6 additions & 0 deletions theseus_gui/src-tauri/src/api/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ pub async fn metadata_get_fabric_versions() -> Result<Manifest> {
pub async fn metadata_get_forge_versions() -> Result<Manifest> {
Ok(theseus::metadata::get_forge_versions().await?)
}

/// Gets the quilt versions from daedalus
#[tauri::command]
pub async fn metadata_get_quilt_versions() -> Result<Manifest> {
Ok(theseus::metadata::get_quilt_versions().await?)
}
Loading