#![expect(
clippy::derive_partial_eq_without_eq,
reason = "Non-`Eq` typed attributes may be added \
to the configuration in the future."
)]
#[cfg(feature = "serde")]
use figment::{
providers::{Format, Serialized, Toml},
Figment,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[cfg(feature = "serde")]
use crate::path::git_root;
#[cfg_attr(
feature = "serde",
doc = "[`read()`](Self::read) and [`figment()`](Self::figment) can be used to obtain configuration from files."
)]
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Config {
pub paths: Paths,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Paths {
pub scripts: ScriptPaths,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct ScriptPaths {
pub system: Vec<PathBuf>,
pub user: Vec<PathBuf>,
pub repository: Vec<PathBuf>,
}
impl Config {
#[cfg(feature = "serde")]
pub fn figment() -> Figment {
let user_home = home::home_dir().unwrap_or_default();
let git_root = git_root().unwrap_or_default();
let mut figment = Figment::new()
.merge(Serialized::defaults(Self::default()))
.merge(Toml::file("/etc/devscripts/config.toml"))
.merge(Toml::file(
user_home.join("./.config/devscripts/config.toml"),
));
if let Some(git_root) = git_root {
figment = figment.merge(Toml::file(git_root.join("./.devscripts/.config.toml")));
}
figment
}
#[cfg(feature = "serde")]
pub fn read() -> Result<Self, figment::Error> {
Self::figment().extract()
}
}
impl Default for ScriptPaths {
fn default() -> Self {
Self {
system: vec![
"/usr/share/devscripts".into(),
"/usr/local/share/devscripts".into(),
],
user: vec!["~/.local/share/devscripts".into()],
repository: vec!["./.devscripts".into()],
}
}
}