You've already forked AstralRinth
182 lines
5.5 KiB
Rust
182 lines
5.5 KiB
Rust
//! Theseus profile management interface
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use io::IOError;
|
|
use tokio::sync::RwLock;
|
|
|
|
use crate::{
|
|
event::emit::{emit_loading, init_loading},
|
|
prelude::DirectoryInfo,
|
|
state::{self, Profiles},
|
|
util::io,
|
|
};
|
|
pub use crate::{
|
|
state::{
|
|
Hooks, JavaSettings, MemorySettings, Profile, Settings, WindowSize,
|
|
},
|
|
State,
|
|
};
|
|
|
|
/// Gets entire settings
|
|
#[tracing::instrument]
|
|
pub async fn get() -> crate::Result<Settings> {
|
|
let state = State::get().await?;
|
|
let settings = state.settings.read().await;
|
|
Ok(settings.clone())
|
|
}
|
|
|
|
/// Sets entire settings
|
|
#[tracing::instrument]
|
|
pub async fn set(settings: Settings) -> crate::Result<()> {
|
|
let state = State::get().await?;
|
|
|
|
if settings.loaded_config_dir
|
|
!= state.settings.read().await.loaded_config_dir
|
|
{
|
|
return Err(crate::ErrorKind::OtherError(
|
|
"Cannot change config directory as setting".to_string(),
|
|
)
|
|
.as_error());
|
|
}
|
|
|
|
let (reset_io, reset_fetch) = async {
|
|
let read = state.settings.read().await;
|
|
(
|
|
settings.max_concurrent_writes != read.max_concurrent_writes,
|
|
settings.max_concurrent_downloads != read.max_concurrent_downloads,
|
|
)
|
|
}
|
|
.await;
|
|
|
|
{
|
|
*state.settings.write().await = settings;
|
|
}
|
|
|
|
if reset_io {
|
|
state.reset_io_semaphore().await;
|
|
}
|
|
if reset_fetch {
|
|
state.reset_fetch_semaphore().await;
|
|
}
|
|
|
|
State::sync().await?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Sets the new config dir, the location of all Theseus data except for the settings.json and caches
|
|
/// Takes control of the entire state and blocks until completion
|
|
pub async fn set_config_dir(new_config_dir: PathBuf) -> crate::Result<()> {
|
|
if !new_config_dir.is_dir() {
|
|
return Err(crate::ErrorKind::FSError(format!(
|
|
"New config dir is not a folder: {}",
|
|
new_config_dir.display()
|
|
))
|
|
.as_error());
|
|
}
|
|
|
|
let loading_bar = init_loading(
|
|
crate::LoadingBarType::ConfigChange {
|
|
new_path: new_config_dir.clone(),
|
|
},
|
|
100.0,
|
|
"Changing configuration directory",
|
|
)
|
|
.await?;
|
|
|
|
tracing::trace!("Changing config dir, taking control of the state");
|
|
// Take control of the state
|
|
let mut state_write = State::get_write().await?;
|
|
let old_config_dir =
|
|
state_write.directories.config_dir.read().await.clone();
|
|
|
|
tracing::trace!("Setting configuration setting");
|
|
// Set load config dir setting
|
|
let settings = {
|
|
let mut settings = state_write.settings.write().await;
|
|
settings.loaded_config_dir = Some(new_config_dir.clone());
|
|
|
|
// Some java paths are hardcoded to within our config dir, so we need to update them
|
|
tracing::trace!("Updating java keys");
|
|
for key in settings.java_globals.keys() {
|
|
if let Some(java) = settings.java_globals.get_mut(&key) {
|
|
// If the path is within the old config dir path, update it to the new config dir
|
|
if let Ok(relative_path) = PathBuf::from(java.path.clone())
|
|
.strip_prefix(&old_config_dir)
|
|
{
|
|
java.path = new_config_dir
|
|
.join(relative_path)
|
|
.to_string_lossy()
|
|
.to_string();
|
|
}
|
|
}
|
|
}
|
|
tracing::trace!("Syncing settings");
|
|
|
|
settings
|
|
.sync(&state_write.directories.settings_file())
|
|
.await?;
|
|
settings.clone()
|
|
};
|
|
|
|
tracing::trace!("Reinitializing directory");
|
|
// Set new state information
|
|
state_write.directories = DirectoryInfo::init(&settings)?;
|
|
let total_entries = std::fs::read_dir(&old_config_dir)
|
|
.map_err(|e| IOError::with_path(e, &old_config_dir))?
|
|
.count() as f64;
|
|
|
|
// Move all files over from state_write.directories.config_dir to new_config_dir
|
|
tracing::trace!("Renaming folder structure");
|
|
let mut i = 0.0;
|
|
let mut entries = io::read_dir(&old_config_dir).await?;
|
|
while let Some(entry) = entries
|
|
.next_entry()
|
|
.await
|
|
.map_err(|e| IOError::with_path(e, &old_config_dir))?
|
|
{
|
|
let entry_path = entry.path();
|
|
if let Some(file_name) = entry_path.file_name() {
|
|
// Ignore settings.json
|
|
if file_name == state::SETTINGS_FILE_NAME {
|
|
continue;
|
|
}
|
|
// Ignore caches folder
|
|
if file_name == state::CACHES_FOLDER_NAME {
|
|
continue;
|
|
}
|
|
// Ignore modrinth_logs folder
|
|
if file_name == state::LAUNCHER_LOGS_FOLDER_NAME {
|
|
continue;
|
|
}
|
|
|
|
let new_path = new_config_dir.join(file_name);
|
|
io::rename(entry_path, new_path).await?;
|
|
|
|
i += 1.0;
|
|
emit_loading(&loading_bar, 90.0 * (i / total_entries), None)
|
|
.await?;
|
|
}
|
|
}
|
|
|
|
// Reset file watcher
|
|
tracing::trace!("Reset file watcher");
|
|
let mut file_watcher = state::init_watcher().await?;
|
|
|
|
// Reset profiles (for filepaths, file watcher, etc)
|
|
state_write.profiles = RwLock::new(
|
|
Profiles::init(&state_write.directories, &mut file_watcher).await?,
|
|
);
|
|
state_write.file_watcher = RwLock::new(file_watcher);
|
|
|
|
emit_loading(&loading_bar, 10.0, None).await?;
|
|
|
|
// TODO: need to be able to safely error out of this function, reverting the changes
|
|
tracing::info!(
|
|
"Successfully switched config folder to: {}",
|
|
new_config_dir.display()
|
|
);
|
|
|
|
Ok(())
|
|
}
|