diff --git a/Cargo.lock b/Cargo.lock index 8320d10..4473ddb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,6 +124,26 @@ dependencies = [ "syn", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "email-encoding" version = "0.1.3" @@ -218,6 +238,17 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -632,6 +663,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -805,6 +847,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.4" @@ -987,6 +1049,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "whakarite" version = "0.1.0" @@ -995,12 +1063,12 @@ dependencies = [ "clap", "diesel", "lettre", - "log", "serde", "time", "toml", "tracing", "tracing-subscriber", + "xdg", ] [[package]] @@ -1090,3 +1158,12 @@ name = "windows_x86_64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "xdg" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6" +dependencies = [ + "dirs", +] diff --git a/Cargo.toml b/Cargo.toml index d0ec283..f962407 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ categories = ["utility"] [dependencies] anyhow = "1" -log = "0.4" tracing = "0.1" tracing-subscriber = "0.3" time = "0.3" @@ -20,3 +19,4 @@ diesel = { version = "2", features = ["postgres", "r2d2", "time"] } serde = { version = "1", features = ["derive"] } toml = "0.6" clap = { version = "4", features = ["derive"] } +xdg = "2" diff --git a/src/args.rs b/src/args.rs index 69864cb..b4b12de 100644 --- a/src/args.rs +++ b/src/args.rs @@ -7,7 +7,7 @@ use tracing::Level; pub struct Args { /// Use a custom config file #[arg(short, long, value_name = "FILE")] - config: Option, + pub config: Option, /// Set a log level #[arg(short, long, value_name = "LEVEL", default_value_t = Level::INFO)] diff --git a/src/config.rs b/src/config.rs index 8ee0351..d1e0eff 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,7 @@ +use anyhow::{bail, Result}; use serde::Deserialize; +use std::{env, fs, path::PathBuf}; +use tracing::{error, info, trace}; fn default_host() -> String { "localhost".to_string() @@ -45,3 +48,43 @@ pub struct Config { /// Database configuration pub database: Database, } + +impl Config { + fn try_paths() -> Result<(PathBuf, String)> { + let file = "config.toml"; + info!(?file, "loading configuration"); + if let Ok(config) = fs::read_to_string(&file) { + return Ok((file.into(), config)); + } + + let user_file = + xdg::BaseDirectories::with_prefix(env!("CARGO_BIN_NAME"))?.get_config_file(file); + info!(file = ?user_file, "loading configuration"); + if let Ok(config) = fs::read_to_string(&user_file) { + return Ok((user_file, config)); + } + + let global_file = format!("/etc/{}/{}", env!("CARGO_BIN_NAME"), file); + info!(file = ?global_file, "loading configuration"); + if let Ok(config) = fs::read_to_string(&global_file) { + return Ok((global_file.into(), config)); + } + + error!("no configuration file found"); + bail!("no configuration file found"); + } + + pub fn load_config(file: Option) -> Result { + if let Some(file) = file { + info!(?file, "loading configuration"); + let config: Config = toml::from_str(&fs::read_to_string(&file)?)?; + trace!(?file, ?config, "loaded configuration"); + Ok(config) + } else { + let (file, config) = Self::try_paths()?; + let config = toml::from_str(&config)?; + trace!(?file, ?config, "loaded configuration"); + Ok(config) + } + } +} diff --git a/src/main.rs b/src/main.rs index 0e31328..9e13b5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,12 +71,7 @@ fn main() -> Result<()> { env!("CARGO_PKG_VERSION") ); - let config_path = "./config.toml"; - - let config: Config = toml::from_str(&std::fs::read_to_string(config_path)?)?; - - trace!(?config, config_path, "loaded config"); - + let config = Config::load_config(args.config)?; let db_pool = Pool::builder().build(ConnectionManager::::new(format!( "postgresql://{}:{}@{}:{}/{}", config.database.user,