Initial draft of profile metadata format & CLI (#17)

* Initial draft of profile metadata format

* Remove records, add Clippy to Nix, fix Clippy error

* Work on profile definition

* BREAKING: Make global settings consistent with profile settings

* Add builder methods & format

* Integrate launching with profiles

* Add profile loading

* Launching via profile, API tweaks, and yak shaving

* Incremental update, committing everything due to personal system maintainance

* Prepare for review cycle

* Remove reminents of experimental work

* CLI: allow people to override the non-empty directory check

* Fix mistake in previous commit

* Handle trailing whitespace and newlines in prompts

* Revamp prompt to use dialoguer and support defaults

* Make requested changes
This commit is contained in:
Danielle
2022-03-28 18:41:35 -07:00
committed by GitHub
parent 98aa66f9d8
commit d1070ca213
27 changed files with 1825 additions and 334 deletions

View File

@@ -1,33 +1,51 @@
use std::path::Path;
use super::profiles::*;
use std::{
collections::HashSet,
path::{Path, PathBuf},
};
use crate::{data::DataError, LAUNCHER_WORK_DIR};
use once_cell::sync;
use serde::{Deserialize, Serialize};
use tokio::sync::{RwLock, RwLockReadGuard};
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
const SETTINGS_FILE: &str = "settings.json";
const ICONS_PATH: &str = "icons";
const METADATA_DIR: &str = "meta";
static SETTINGS: sync::OnceCell<RwLock<Settings>> = sync::OnceCell::new();
pub const FORMAT_VERSION: u32 = 1;
#[derive(Clone, Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct Settings {
pub memory: i32,
pub game_resolution: (i32, i32),
pub custom_java_args: String,
pub java_8_path: Option<String>,
pub java_17_path: Option<String>,
pub wrapper_command: Option<String>,
pub memory: MemorySettings,
pub game_resolution: WindowSize,
pub custom_java_args: Vec<String>,
pub java_8_path: Option<PathBuf>,
pub java_17_path: Option<PathBuf>,
pub hooks: ProfileHooks,
pub icon_path: PathBuf,
pub metadata_dir: PathBuf,
pub profiles: HashSet<PathBuf>,
pub max_concurrent_downloads: usize,
pub version: u32,
}
impl Default for Settings {
fn default() -> Self {
Self {
memory: 2048,
game_resolution: (854, 480),
custom_java_args: "".to_string(),
memory: MemorySettings::default(),
game_resolution: WindowSize::default(),
custom_java_args: Vec::new(),
java_8_path: None,
java_17_path: None,
wrapper_command: None,
hooks: ProfileHooks::default(),
icon_path: Path::new(LAUNCHER_WORK_DIR).join(ICONS_PATH),
metadata_dir: Path::new(LAUNCHER_WORK_DIR).join(METADATA_DIR),
profiles: HashSet::new(),
max_concurrent_downloads: 32,
version: FORMAT_VERSION,
}
}
}
@@ -50,10 +68,14 @@ impl Settings {
if SETTINGS.get().is_none() {
let new = Self::default();
std::fs::write(
tokio::fs::rename(SETTINGS_FILE, format!("{SETTINGS_FILE}.bak"))
.await?;
tokio::fs::write(
Path::new(LAUNCHER_WORK_DIR).join(SETTINGS_FILE),
&serde_json::to_string(&new)?,
)?;
)
.await?;
SETTINGS.get_or_init(|| RwLock::new(new));
}
@@ -66,7 +88,7 @@ impl Settings {
Path::new(LAUNCHER_WORK_DIR).join(SETTINGS_FILE),
)?)?;
let write = &mut *SETTINGS
let mut write = SETTINGS
.get()
.ok_or_else(|| DataError::InitializedError("settings".to_string()))?
.write()
@@ -82,17 +104,24 @@ impl Settings {
std::fs::write(
Path::new(LAUNCHER_WORK_DIR).join(SETTINGS_FILE),
&serde_json::to_string(&*settings)?,
&serde_json::to_string_pretty(&*settings)?,
)?;
Ok(())
}
pub async fn get<'a>() -> Result<RwLockReadGuard<'a, Self>, DataError> {
Ok(SETTINGS
Ok(Self::get_or_uninit::<'a>()?.read().await)
}
pub async fn get_mut<'a>() -> Result<RwLockWriteGuard<'a, Self>, DataError>
{
Ok(Self::get_or_uninit::<'a>()?.write().await)
}
fn get_or_uninit<'a>() -> Result<&'a RwLock<Self>, DataError> {
SETTINGS
.get()
.ok_or_else(|| DataError::InitializedError("settings".to_string()))?
.read()
.await)
.ok_or_else(|| DataError::InitializedError("settings".to_string()))
}
}