use anyhow::Result;
use std::fs;
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct Config {
pub color: bool,
pub auto_update_grub: bool,
pub kernel_filter: KernelFilter,
pub history_max_entries: usize,
pub updates: UpdateConfig,
}
#[derive(Debug, Clone, Default)]
pub struct KernelFilter {
pub hide_debug: bool,
pub hide_unsigned: bool,
pub hide_rt: bool,
}
#[derive(Debug, Clone)]
pub struct UpdateConfig {
pub check_enabled: bool,
pub check_url: String,
pub last_checked: Option<String>,
pub check_interval_hours: u64,
}
impl Default for Config {
fn default() -> Self {
Self {
color: true,
auto_update_grub: true,
kernel_filter: KernelFilter::default(),
history_max_entries: 50,
updates: UpdateConfig::default(),
}
}
}
impl Default for UpdateConfig {
fn default() -> Self {
Self {
check_enabled: true,
check_url: "https://crates.io/api/v1/crates/rustpm".to_string(),
last_checked: None,
check_interval_hours: 24,
}
}
}
fn config_path() -> PathBuf {
let home = std::env::var("HOME").unwrap_or_else(|_| "/root".to_string());
PathBuf::from(home).join(".config").join("rustpm").join("config")
}
impl Config {
pub fn load() -> Result<Self> {
let path = config_path();
if !path.exists() {
return Ok(Self::default());
}
let content = fs::read_to_string(&path)?;
Ok(Self::parse(&content))
}
fn parse(content: &str) -> Self {
let mut cfg = Self::default();
for line in content.lines() {
let line = line.trim();
if line.starts_with('#') || line.is_empty() {
continue;
}
if let Some((key, val)) = line.split_once('=') {
let key = key.trim();
let val = val.trim();
match key {
"color" => cfg.color = val == "true",
"auto_update_grub" => cfg.auto_update_grub = val == "true",
"history_max_entries" => cfg.history_max_entries = val.parse().unwrap_or(50),
"hide_debug" => cfg.kernel_filter.hide_debug = val == "true",
"hide_unsigned" => cfg.kernel_filter.hide_unsigned = val == "true",
"hide_rt" => cfg.kernel_filter.hide_rt = val == "true",
"check_enabled" => cfg.updates.check_enabled = val == "true",
"check_url" => cfg.updates.check_url = val.to_string(),
"check_interval_hours" => cfg.updates.check_interval_hours = val.parse().unwrap_or(24),
_ => {}
}
}
}
cfg
}
pub fn save(&self) -> Result<()> {
let path = config_path();
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let content = format!(
"color = {}\nauto_update_grub = {}\nhistory_max_entries = {}\n\
hide_debug = {}\nhide_unsigned = {}\nhide_rt = {}\n\n\
check_enabled = {}\ncheck_url = {}\ncheck_interval_hours = {}\n",
self.color,
self.auto_update_grub,
self.history_max_entries,
self.kernel_filter.hide_debug,
self.kernel_filter.hide_unsigned,
self.kernel_filter.hide_rt,
self.updates.check_enabled,
self.updates.check_url,
self.updates.check_interval_hours,
);
fs::write(&path, content)?;
Ok(())
}
}