From 22a36d483e28d8e18d954c5354cbb99b7620c1c6 Mon Sep 17 00:00:00 2001 From: Josh Junon Date: Tue, 5 Mar 2024 12:45:51 +0100 Subject: [PATCH] add config file --- Cargo.lock | 33 ++++++++++++--- gitbutler-app/Cargo.toml | 1 + gitbutler-app/src/config.rs | 83 +++++++++++++++++++++++++++++++++++++ gitbutler-app/src/main.rs | 2 + 4 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 gitbutler-app/src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 2b0b25fee..32e81cf35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1973,6 +1973,7 @@ dependencies = [ "thiserror", "tokio", "tokio-util", + "toml 0.8.10", "tracing", "tracing-appender", "tracing-subscriber", @@ -4185,7 +4186,7 @@ dependencies = [ "siphasher 1.0.0", "thiserror", "time", - "toml 0.8.8", + "toml 0.8.10", "url", "walkdir", ] @@ -5842,14 +5843,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.22.6", ] [[package]] @@ -5871,7 +5872,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.15", ] [[package]] @@ -5879,12 +5880,23 @@ name = "toml_edit" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow 0.5.15", +] + +[[package]] +name = "toml_edit" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" dependencies = [ "indexmap 2.0.0", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.5", ] [[package]] @@ -6796,6 +6808,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/gitbutler-app/Cargo.toml b/gitbutler-app/Cargo.toml index c7daa70f8..c8cc527fc 100644 --- a/gitbutler-app/Cargo.toml +++ b/gitbutler-app/Cargo.toml @@ -66,6 +66,7 @@ log = "^0.4" thiserror.workspace = true tokio = { workspace = true, features = [ "full", "sync" ] } tokio-util = "0.7.10" +toml = "0.8.10" tracing = "0.1.40" tracing-appender = "0.2.3" tracing-subscriber = "0.3.17" diff --git a/gitbutler-app/src/config.rs b/gitbutler-app/src/config.rs new file mode 100644 index 000000000..f13bd78b5 --- /dev/null +++ b/gitbutler-app/src/config.rs @@ -0,0 +1,83 @@ +use serde::{Deserialize, Serialize}; +use tauri::AppHandle; + +/// Configuration loaded from `$config_dir/gitbutler.toml` +#[derive(Clone, Serialize, Deserialize, Default)] +#[serde(rename_all = "kebab-case")] +pub struct Config { + #[serde(skip_serializing_if = "Option::is_none")] + pub theme: Option, +} + +/// Custom theme configuration for the app +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct Theme { + pub base: ThemeBase, + #[serde(skip_serializing_if = "Option::is_none")] + pub core_ntrl_100: Option, +} + +/// The base theme on which styles are applied +#[derive(Clone, Copy, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ThemeBase { + /// Theme modifications are based on the light theme + Light, + /// Theme modifications are based on the dark theme + Dark, +} + +/// Errors that may arise when reading/writing config files +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("i/o error: {1}: {0}")] + Io(String, std::io::Error), + #[error("toml error: {0}")] + Toml(String), +} + +impl Serialize for Error { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.to_string().as_ref()) + } +} + +/// Loads the configuration from `$config_dir/gitbutler.toml` +#[tauri::command(async)] +pub async fn load_config(handle: AppHandle) -> Result { + let Some(config_dir) = handle.path_resolver().app_config_dir() else { + tracing::warn!("failed to get app config dir (none returned)"); + return Ok(Config::default()); + }; + + let config_path = config_dir.join("gitbutler.toml"); + + match tokio::fs::read_to_string(&config_path).await { + Ok(contents) => { + tracing::debug!("loaded config from: {}", config_path.display()); + toml::from_str(&contents).map_err(|err| Error::Toml(err.to_string())) + } + Err(err) => { + if err.kind() == std::io::ErrorKind::NotFound { + tracing::warn!("config file not found: {}", config_path.display()); + let config = Config::default(); + + // Write it back out, only warning if it fails, returning the default config + // in either case + if let Err(err) = + tokio::fs::write(&config_path, toml::to_string(&config).unwrap()).await + { + tracing::warn!("failed to write default config: {}", err); + } + + Ok(config) + } else { + Err(Error::Io(config_path.display().to_string(), err)) + } + } + } +} diff --git a/gitbutler-app/src/main.rs b/gitbutler-app/src/main.rs index 549f8eecf..f2bb1122c 100644 --- a/gitbutler-app/src/main.rs +++ b/gitbutler-app/src/main.rs @@ -5,6 +5,7 @@ pub(crate) mod analytics; pub(crate) mod app; pub(crate) mod assets; pub(crate) mod commands; +pub(crate) mod config; pub(crate) mod database; pub(crate) mod dedup; pub(crate) mod deltas; @@ -198,6 +199,7 @@ fn main() { commands::git_set_global_config, commands::git_get_global_config, commands::project_flush_and_push, + config::load_config, zip::commands::get_logs_archive_path, zip::commands::get_project_archive_path, zip::commands::get_project_data_archive_path,