Skip to content

Commit

Permalink
Performance improvements (#114)
Browse files Browse the repository at this point in the history
* Performance improvements

* run fmt

* optimize creation modal

* remove print, fix mod loader editing

* Fix library update

* update extract loading bar

* Update theseus_gui/src-tauri/src/api/metadata.rs

Co-authored-by: triphora <emma@modrinth.com>

* fix cli

---------

Co-authored-by: triphora <emma@modrinth.com>
  • Loading branch information
Geometrically and triphora committed May 12, 2023
1 parent 7a0798d commit ee0c91a
Show file tree
Hide file tree
Showing 28 changed files with 324 additions and 232 deletions.
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

0 comments on commit ee0c91a

Please sign in to comment.