Load config from file

This commit is contained in:
Joscha 2023-08-04 17:21:59 +02:00
parent 6f95d58e11
commit 4f7d4f3204
5 changed files with 144 additions and 7 deletions

92
Cargo.lock generated
View file

@ -547,6 +547,27 @@ dependencies = [
"subtle", "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]] [[package]]
name = "dotenvy" name = "dotenvy"
version = "0.15.7" version = "0.15.7"
@ -1924,6 +1945,12 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -2137,6 +2164,17 @@ dependencies = [
"bitflags 1.3.2", "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]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.3.4" version = "0.3.4"
@ -2247,18 +2285,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.180" version = "1.0.181"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed" checksum = "6d3e73c93c3240c0bda063c239298e633114c69a888c3e37ca8bb33f343e9890"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.180" version = "1.0.181"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036" checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2286,6 +2324,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_spanned"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_urlencoded" name = "serde_urlencoded"
version = "0.7.1" version = "0.7.1"
@ -2684,11 +2731,14 @@ dependencies = [
"askama_axum", "askama_axum",
"axum", "axum",
"clap", "clap",
"directories",
"gix", "gix",
"mime_guess", "mime_guess",
"rust-embed", "rust-embed",
"serde",
"sqlx", "sqlx",
"tokio", "tokio",
"toml",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"vergen", "vergen",
@ -2825,6 +2875,40 @@ dependencies = [
"tokio", "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]] [[package]]
name = "tower" name = "tower"
version = "0.4.13" version = "0.4.13"

View file

@ -9,11 +9,14 @@ askama = { version = "0.12.0", features = ["with-axum"] }
askama_axum = "0.3.0" askama_axum = "0.3.0"
axum = { version = "0.6.19", features = ["macros"] } axum = { version = "0.6.19", features = ["macros"] }
clap = { version = "4.3.19", features = ["derive", "deprecated"] } clap = { version = "4.3.19", features = ["derive", "deprecated"] }
directories = "5.0.1"
gix = "0.51.0" gix = "0.51.0"
mime_guess = "2.0.4" mime_guess = "2.0.4"
rust-embed = "6.8.1" rust-embed = "6.8.1"
serde = { version = "1.0.181", features = ["derive"] }
sqlx = { version = "0.7.1", features = ["runtime-tokio", "sqlite"] } sqlx = { version = "0.7.1", features = ["runtime-tokio", "sqlite"] }
tokio = { version = "1.29.1", features = ["full"] } tokio = { version = "1.29.1", features = ["full"] }
toml = "0.7.6"
tracing = "0.1.37" tracing = "0.1.37"
tracing-subscriber = "0.3.17" tracing-subscriber = "0.3.17"

23
src/config.rs Normal file
View file

@ -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<Self> {
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)?,
})
}
}

View file

@ -1,3 +1,4 @@
mod config;
mod state; mod state;
mod r#static; mod r#static;
@ -7,12 +8,15 @@ use askama::Template;
use askama_axum::{IntoResponse, Response}; use askama_axum::{IntoResponse, Response};
use axum::{extract::State, http::StatusCode, routing::get, Router}; use axum::{extract::State, http::StatusCode, routing::get, Router};
use clap::Parser; use clap::Parser;
use directories::ProjectDirs;
use sqlx::SqlitePool; use sqlx::SqlitePool;
use state::AppState; use state::AppState;
use tokio::{select, signal::unix::SignalKind}; use tokio::{select, signal::unix::SignalKind};
use tracing::{debug, info}; use tracing::{debug, info};
use tracing_subscriber::filter::LevelFilter; use tracing_subscriber::filter::LevelFilter;
use crate::config::Config;
const NAME: &str = env!("CARGO_PKG_NAME"); const NAME: &str = env!("CARGO_PKG_NAME");
const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", env!("VERGEN_GIT_SHA"), ")"); const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", env!("VERGEN_GIT_SHA"), ")");
@ -23,6 +27,9 @@ struct Args {
db: PathBuf, db: PathBuf,
/// Path to the git repo. /// Path to the git repo.
repo: PathBuf, repo: PathBuf,
/// Path to the config file.
#[arg(long, short)]
config: Option<PathBuf>,
/// Enable more verbose output /// Enable more verbose output
#[arg(long, short)] #[arg(long, short)]
verbose: bool, verbose: bool,
@ -42,6 +49,17 @@ fn set_up_logging(verbose: bool) {
} }
} }
fn load_config(path: Option<PathBuf>) -> 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<()> { async fn wait_for_signal() -> io::Result<()> {
debug!("Listening to signals"); debug!("Listening to signals");
@ -79,7 +97,8 @@ async fn run() -> anyhow::Result<()> {
set_up_logging(args.verbose); set_up_logging(args.verbose);
info!("You are running {NAME} {VERSION}"); 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() let app = Router::new()
.route("/", get(index)) .route("/", get(index))

View file

@ -8,7 +8,9 @@ use sqlx::{
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous}, sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous},
SqlitePool, SqlitePool,
}; };
use tracing::{info, debug}; use tracing::{debug, info};
use crate::config::Config;
// TODO Occasionally run PRAGMA optimize // TODO Occasionally run PRAGMA optimize
async fn open_db(db_path: &Path) -> sqlx::Result<SqlitePool> { async fn open_db(db_path: &Path) -> sqlx::Result<SqlitePool> {
@ -43,13 +45,19 @@ fn open_repo(repo_path: &Path) -> anyhow::Result<ThreadSafeRepository> {
#[derive(Clone, FromRef)] #[derive(Clone, FromRef)]
pub struct AppState { pub struct AppState {
pub config: &'static Config,
pub db: SqlitePool, pub db: SqlitePool,
pub repo: Arc<ThreadSafeRepository>, pub repo: Arc<ThreadSafeRepository>,
} }
impl AppState { impl AppState {
pub async fn new(db_path: &Path, repo_path: &Path) -> anyhow::Result<Self> { pub async fn new(
config: &'static Config,
db_path: &Path,
repo_path: &Path,
) -> anyhow::Result<Self> {
Ok(Self { Ok(Self {
config,
db: open_db(db_path).await?, db: open_db(db_path).await?,
repo: Arc::new(open_repo(repo_path)?), repo: Arc::new(open_repo(repo_path)?),
}) })