From 4f7d4f3204896ffe61295cc02ed9f9d1320eb430 Mon Sep 17 00:00:00 2001 From: Joscha Date: Fri, 4 Aug 2023 17:21:59 +0200 Subject: [PATCH] Load config from file --- Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 3 ++ src/config.rs | 23 +++++++++++++ src/main.rs | 21 +++++++++++- src/state.rs | 12 +++++-- 5 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 3ea0d13..802a055 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -547,6 +547,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -1924,6 +1945,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -2137,6 +2164,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "regex-automata" version = "0.3.4" @@ -2247,18 +2285,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.180" +version = "1.0.181" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed" +checksum = "6d3e73c93c3240c0bda063c239298e633114c69a888c3e37ca8bb33f343e9890" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.180" +version = "1.0.181" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036" +checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed" dependencies = [ "proc-macro2", "quote", @@ -2286,6 +2324,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2684,11 +2731,14 @@ dependencies = [ "askama_axum", "axum", "clap", + "directories", "gix", "mime_guess", "rust-embed", + "serde", "sqlx", "tokio", + "toml", "tracing", "tracing-subscriber", "vergen", @@ -2825,6 +2875,40 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" diff --git a/Cargo.toml b/Cargo.toml index ca90463..262be5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,11 +9,14 @@ askama = { version = "0.12.0", features = ["with-axum"] } askama_axum = "0.3.0" axum = { version = "0.6.19", features = ["macros"] } clap = { version = "4.3.19", features = ["derive", "deprecated"] } +directories = "5.0.1" gix = "0.51.0" mime_guess = "2.0.4" rust-embed = "6.8.1" +serde = { version = "1.0.181", features = ["derive"] } sqlx = { version = "0.7.1", features = ["runtime-tokio", "sqlite"] } tokio = { version = "1.29.1", features = ["full"] } +toml = "0.7.6" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..481d6be --- /dev/null +++ b/src/config.rs @@ -0,0 +1,23 @@ +//! Configuration from a file. + +use std::{fs, io::ErrorKind, path::Path}; + +use serde::Deserialize; +use tracing::info; + +#[derive(Debug, Default, Deserialize)] +pub struct Config {} + +impl Config { + pub fn load(path: &Path) -> anyhow::Result { + info!("Loading config from {}", path.display()); + Ok(match fs::read_to_string(path) { + Ok(str) => toml::from_str(&str)?, + Err(e) if e.kind() == ErrorKind::NotFound => { + info!("No config file found, using default config"); + Self::default() + } + Err(e) => Err(e)?, + }) + } +} diff --git a/src/main.rs b/src/main.rs index a28f1bd..e859aa7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod config; mod state; mod r#static; @@ -7,12 +8,15 @@ use askama::Template; use askama_axum::{IntoResponse, Response}; use axum::{extract::State, http::StatusCode, routing::get, Router}; use clap::Parser; +use directories::ProjectDirs; use sqlx::SqlitePool; use state::AppState; use tokio::{select, signal::unix::SignalKind}; use tracing::{debug, info}; use tracing_subscriber::filter::LevelFilter; +use crate::config::Config; + const NAME: &str = env!("CARGO_PKG_NAME"); const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", env!("VERGEN_GIT_SHA"), ")"); @@ -23,6 +27,9 @@ struct Args { db: PathBuf, /// Path to the git repo. repo: PathBuf, + /// Path to the config file. + #[arg(long, short)] + config: Option, /// Enable more verbose output #[arg(long, short)] verbose: bool, @@ -42,6 +49,17 @@ fn set_up_logging(verbose: bool) { } } +fn load_config(path: Option) -> anyhow::Result<&'static Config> { + let config_path = path.unwrap_or_else(|| { + ProjectDirs::from("de", "plugh", "tablejohn") + .expect("could not determine home directory") + .config_dir() + .join("config.toml") + }); + + Ok(Box::leak(Box::new(Config::load(&config_path)?))) +} + async fn wait_for_signal() -> io::Result<()> { debug!("Listening to signals"); @@ -79,7 +97,8 @@ async fn run() -> anyhow::Result<()> { set_up_logging(args.verbose); info!("You are running {NAME} {VERSION}"); - let state = AppState::new(&args.db, &args.repo).await?; + let config = load_config(args.config)?; + let state = AppState::new(config, &args.db, &args.repo).await?; let app = Router::new() .route("/", get(index)) diff --git a/src/state.rs b/src/state.rs index 6e8854f..3a03534 100644 --- a/src/state.rs +++ b/src/state.rs @@ -8,7 +8,9 @@ use sqlx::{ sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous}, SqlitePool, }; -use tracing::{info, debug}; +use tracing::{debug, info}; + +use crate::config::Config; // TODO Occasionally run PRAGMA optimize async fn open_db(db_path: &Path) -> sqlx::Result { @@ -43,13 +45,19 @@ fn open_repo(repo_path: &Path) -> anyhow::Result { #[derive(Clone, FromRef)] pub struct AppState { + pub config: &'static Config, pub db: SqlitePool, pub repo: Arc, } impl AppState { - pub async fn new(db_path: &Path, repo_path: &Path) -> anyhow::Result { + pub async fn new( + config: &'static Config, + db_path: &Path, + repo_path: &Path, + ) -> anyhow::Result { Ok(Self { + config, db: open_db(db_path).await?, repo: Arc::new(open_repo(repo_path)?), })