Skip to content

Commit

Permalink
String settings hooks (#82)
Browse files Browse the repository at this point in the history
* added theme; env change

* began refactoring

* added process hook

* now singular string for each hook

* fixed splitting by comma to by space

* profile_create function updated

* prettier

* added jre validator

* restructured so that it doesnt look like a vec

* fixed merge issue

* snake case

* resolved merge issues + added process events

* clippy, fmt

* removed unnecssary func
  • Loading branch information
thesuzerain authored Apr 17, 2023
1 parent b120b5c commit 9f40640
Show file tree
Hide file tree
Showing 23 changed files with 473 additions and 210 deletions.
79 changes: 79 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions theseus/src/api/jre.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//! Authentication flow interface
use std::path::PathBuf;

use crate::{
launcher::download,
prelude::Profile,
Expand Down Expand Up @@ -139,3 +141,8 @@ pub async fn validate_globals() -> crate::Result<bool> {
let settings = state.settings.read().await;
Ok(settings.java_globals.is_all_valid())
}

// Validates JRE at a given at a given path
pub async fn check_jre(path: PathBuf) -> crate::Result<Option<JavaVersion>> {
Ok(jre::check_java_at_filepath(&path))
}
2 changes: 1 addition & 1 deletion theseus/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub mod tags;
pub mod data {
pub use crate::state::{
DirectoryInfo, Hooks, JavaSettings, MemorySettings, ModLoader,
ProfileMetadata, Settings, WindowSize,
ProfileMetadata, Settings, Theme, WindowSize,
};
}

Expand Down
4 changes: 2 additions & 2 deletions theseus/src/api/pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ async fn install_pack(
.await?;

let loading_bar = init_loading(
LoadingBarType::PackDownload {
pack_name ,
LoadingBarType::PackDownload {
pack_name,
pack_id: project_id,
pack_version: version_id,
},
Expand Down
86 changes: 51 additions & 35 deletions theseus/src/api/process.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Theseus process management interface
use std::path::{Path, PathBuf};

use uuid::Uuid;

use crate::state::MinecraftChild;
pub use crate::{
state::{
Expand All @@ -9,31 +11,33 @@ pub use crate::{
State,
};

// Gets whether a child process stored in the state by PID has finished
// Gets whether a child process stored in the state by UUID has finished
#[tracing::instrument]
pub async fn has_finished_by_pid(pid: u32) -> crate::Result<bool> {
Ok(get_exit_status_by_pid(pid).await?.is_some())
pub async fn has_finished_by_uuid(uuid: &Uuid) -> crate::Result<bool> {
Ok(get_exit_status_by_uuid(uuid).await?.is_some())
}

// Gets the exit status of a child process stored in the state by PID
// Gets the exit status of a child process stored in the state by UUID
#[tracing::instrument]
pub async fn get_exit_status_by_pid(pid: u32) -> crate::Result<Option<i32>> {
pub async fn get_exit_status_by_uuid(
uuid: &Uuid,
) -> crate::Result<Option<i32>> {
let state = State::get().await?;
let children = state.children.read().await;
Ok(children.exit_status(&pid).await?.and_then(|f| f.code()))
Ok(children.exit_status(uuid).await?.and_then(|f| f.code()))
}

// Gets the PID of each stored process in the state
// Gets the UUID of each stored process in the state
#[tracing::instrument]
pub async fn get_all_pids() -> crate::Result<Vec<u32>> {
pub async fn get_all_uuids() -> crate::Result<Vec<Uuid>> {
let state = State::get().await?;
let children = state.children.read().await;
Ok(children.keys())
}

// Gets the PID of each *running* stored process in the state
// Gets the UUID of each *running* stored process in the state
#[tracing::instrument]
pub async fn get_all_running_pids() -> crate::Result<Vec<u32>> {
pub async fn get_all_running_uuids() -> crate::Result<Vec<Uuid>> {
let state = State::get().await?;
let children = state.children.read().await;
children.running_keys().await
Expand All @@ -55,62 +59,62 @@ pub async fn get_all_running_profiles() -> crate::Result<Vec<Profile>> {
children.running_profiles().await
}

// Gets the PID of each stored process in the state by profile path
// Gets the UUID of each stored process in the state by profile path
#[tracing::instrument]
pub async fn get_pids_by_profile_path(
pub async fn get_uuids_by_profile_path(
profile_path: &Path,
) -> crate::Result<Vec<u32>> {
) -> crate::Result<Vec<Uuid>> {
let state = State::get().await?;
let children = state.children.read().await;
children.running_keys_with_profile(profile_path).await
}

// Gets stdout of a child process stored in the state by PID, as a string
// Gets stdout of a child process stored in the state by UUID, as a string
#[tracing::instrument]
pub async fn get_stdout_by_pid(pid: u32) -> crate::Result<String> {
pub async fn get_stdout_by_uuid(uuid: &Uuid) -> crate::Result<String> {
let state = State::get().await?;
// Get stdout from child
let children = state.children.read().await;

// Extract child or return crate::Error
if let Some(child) = children.get(&pid) {
if let Some(child) = children.get(uuid) {
let child = child.read().await;
Ok(child.stdout.get_output().await?)
} else {
Err(crate::ErrorKind::LauncherError(format!(
"No child process with PID {}",
pid
"No child process by UUID {}",
uuid
))
.as_error())
}
}

// Gets stderr of a child process stored in the state by PID, as a string
// Gets stderr of a child process stored in the state by UUID, as a string
#[tracing::instrument]
pub async fn get_stderr_by_pid(pid: u32) -> crate::Result<String> {
pub async fn get_stderr_by_uuid(uuid: &Uuid) -> crate::Result<String> {
let state = State::get().await?;
// Get stdout from child
let children = state.children.read().await;

// Extract child or return crate::Error
if let Some(child) = children.get(&pid) {
if let Some(child) = children.get(uuid) {
let child = child.read().await;
Ok(child.stderr.get_output().await?)
} else {
Err(crate::ErrorKind::LauncherError(format!(
"No child process with PID {}",
pid
"No child process with UUID {}",
uuid
))
.as_error())
}
}

// Kill a child process stored in the state by PID, as a string
// Kill a child process stored in the state by UUID, as a string
#[tracing::instrument]
pub async fn kill_by_pid(pid: u32) -> crate::Result<()> {
pub async fn kill_by_uuid(uuid: &Uuid) -> crate::Result<()> {
let state = State::get().await?;
let children = state.children.read().await;
if let Some(mchild) = children.get(&pid) {
if let Some(mchild) = children.get(uuid) {
let mut mchild = mchild.write().await;
kill(&mut mchild).await
} else {
Expand All @@ -119,13 +123,13 @@ pub async fn kill_by_pid(pid: u32) -> crate::Result<()> {
}
}

// Wait for a child process stored in the state by PID
// Wait for a child process stored in the state by UUID
#[tracing::instrument]
pub async fn wait_for_by_pid(pid: u32) -> crate::Result<()> {
pub async fn wait_for_by_uuid(uuid: &Uuid) -> crate::Result<()> {
let state = State::get().await?;
let children = state.children.read().await;
// No error returned for already killed process
if let Some(mchild) = children.get(&pid) {
if let Some(mchild) = children.get(uuid) {
let mut mchild = mchild.write().await;
wait_for(&mut mchild).await
} else {
Expand All @@ -137,18 +141,30 @@ pub async fn wait_for_by_pid(pid: u32) -> crate::Result<()> {
// Kill a running child process directly, and wait for it to be killed
#[tracing::instrument]
pub async fn kill(running: &mut MinecraftChild) -> crate::Result<()> {
running.child.kill().await?;
running.current_child.write().await.kill().await?;
wait_for(running).await
}

// Await on the completion of a child process directly
#[tracing::instrument]
pub async fn wait_for(running: &mut MinecraftChild) -> crate::Result<()> {
let result = running.child.wait().await.map_err(|err| {
crate::ErrorKind::LauncherError(format!(
"Error running minecraft: {err}"
))
})?;
// We do not wait on the Child directly, but wait on the thread manager.
// This way we can still run all cleanup hook functions that happen after.
let result = running
.manager
.take()
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"Process manager already completed or missing for process {}",
running.uuid
))
})?
.await?
.map_err(|err| {
crate::ErrorKind::LauncherError(format!(
"Error running minecraft: {err}"
))
})?;

match result.success() {
false => Err(crate::ErrorKind::LauncherError(format!(
Expand Down
Loading

0 comments on commit 9f40640

Please sign in to comment.