Ugh
This commit is contained in:
168
src/config.rs
168
src/config.rs
@@ -1,10 +1,10 @@
|
||||
use std::path::PathBuf;
|
||||
use std::fs;
|
||||
use anyhow::{Result, Context};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use log::{debug, error};
|
||||
use crate::args::{Args};
|
||||
use crate::args::Args;
|
||||
use anyhow::{Context, Result};
|
||||
use dirs;
|
||||
use log::{debug, error};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
@@ -122,10 +122,10 @@ impl<'de> serde::Deserialize<'de> for ColumnConfig {
|
||||
#[serde(default)]
|
||||
padding: Option<(u16, u16)>,
|
||||
}
|
||||
|
||||
|
||||
let helper = Helper::deserialize(deserializer)?;
|
||||
let label = helper.label.unwrap_or_else(|| helper.name.clone());
|
||||
|
||||
|
||||
Ok(ColumnConfig {
|
||||
name: helper.name,
|
||||
label,
|
||||
@@ -188,14 +188,17 @@ pub struct Settings {
|
||||
impl Settings {
|
||||
/// Create unified settings from config and args with proper priority
|
||||
pub fn new(args: &Args, default_dir: PathBuf) -> Result<Self> {
|
||||
debug!("CONFIG: Creating settings with default dir: {:?}", default_dir);
|
||||
|
||||
debug!(
|
||||
"CONFIG: Creating settings with default dir: {:?}",
|
||||
default_dir
|
||||
);
|
||||
|
||||
let config_path = if let Some(config_path) = &args.options.config {
|
||||
config_path.clone()
|
||||
} else if let Ok(env_config) = std::env::var("KEEP_CONFIG") {
|
||||
PathBuf::from(env_config)
|
||||
} else {
|
||||
let default_path = if let Some(home_dir) = std::env::var("HOME").ok() {
|
||||
let default_path = if let Ok(home_dir) = std::env::var("HOME") {
|
||||
let mut path = PathBuf::from(home_dir);
|
||||
path.push(".config");
|
||||
path.push("keep");
|
||||
@@ -207,74 +210,82 @@ impl Settings {
|
||||
debug!("CONFIG: Using default config path: {:?}", default_path);
|
||||
default_path
|
||||
};
|
||||
|
||||
|
||||
debug!("CONFIG: Using config path: {:?}", config_path);
|
||||
|
||||
let mut config_builder = config::Config::builder();
|
||||
|
||||
|
||||
// Load config file if it exists
|
||||
if config_path.exists() {
|
||||
debug!("CONFIG: Loading config file: {:?}", config_path);
|
||||
config_builder = config_builder.add_source(config::File::from(config_path.clone()).required(false));
|
||||
config_builder =
|
||||
config_builder.add_source(config::File::from(config_path.clone()).required(false));
|
||||
} else {
|
||||
debug!("CONFIG: Config file does not exist: {:?}", config_path);
|
||||
}
|
||||
|
||||
|
||||
// Add environment variables
|
||||
debug!("CONFIG: Adding environment variables");
|
||||
let env_source = config::Environment::with_prefix("KEEP").separator("__").ignore_empty(true);
|
||||
let env_source = config::Environment::with_prefix("KEEP")
|
||||
.separator("__")
|
||||
.ignore_empty(true);
|
||||
config_builder = config_builder.add_source(env_source);
|
||||
|
||||
|
||||
// Override with CLI args
|
||||
if let Some(dir) = &args.options.dir {
|
||||
debug!("CONFIG: Overriding dir with CLI arg: {:?}", dir);
|
||||
config_builder = config_builder.set_override("dir", dir.to_str().unwrap())?;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if args.options.human_readable {
|
||||
config_builder = config_builder.set_override("human_readable", true)?;
|
||||
}
|
||||
|
||||
|
||||
if let Some(output_format) = &args.options.output_format {
|
||||
config_builder = config_builder.set_override("output_format", output_format.as_str())?;
|
||||
config_builder =
|
||||
config_builder.set_override("output_format", output_format.as_str())?;
|
||||
}
|
||||
|
||||
|
||||
if args.options.verbose > 0 {
|
||||
config_builder = config_builder.set_override("verbose", args.options.verbose)?;
|
||||
}
|
||||
|
||||
|
||||
if args.options.quiet {
|
||||
config_builder = config_builder.set_override("quiet", true)?;
|
||||
}
|
||||
|
||||
|
||||
if args.options.force {
|
||||
config_builder = config_builder.set_override("force", true)?;
|
||||
}
|
||||
|
||||
|
||||
if let Some(server_password) = &args.options.server_password {
|
||||
config_builder = config_builder.set_override("server.password", server_password.as_str())?;
|
||||
config_builder =
|
||||
config_builder.set_override("server.password", server_password.as_str())?;
|
||||
}
|
||||
|
||||
|
||||
if let Some(server_password_hash) = &args.options.server_password_hash {
|
||||
config_builder = config_builder.set_override("server.password_hash", server_password_hash.as_str())?;
|
||||
config_builder = config_builder
|
||||
.set_override("server.password_hash", server_password_hash.as_str())?;
|
||||
}
|
||||
|
||||
|
||||
if let Some(server_address) = &args.mode.server_address {
|
||||
config_builder = config_builder.set_override("server.address", server_address.as_str())?;
|
||||
config_builder =
|
||||
config_builder.set_override("server.address", server_address.as_str())?;
|
||||
}
|
||||
|
||||
|
||||
if let Some(server_port) = args.mode.server_port {
|
||||
config_builder = config_builder.set_override("server.port", server_port)?;
|
||||
}
|
||||
|
||||
|
||||
if let Some(compression) = &args.item.compression {
|
||||
config_builder = config_builder.set_override("compression_plugin.name", compression.as_str())?;
|
||||
config_builder =
|
||||
config_builder.set_override("compression_plugin.name", compression.as_str())?;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if !args.item.meta_plugins.is_empty() {
|
||||
let meta_plugins: Vec<std::collections::HashMap<String, String>> = args.item.meta_plugins
|
||||
let meta_plugins: Vec<std::collections::HashMap<String, String>> = args
|
||||
.item
|
||||
.meta_plugins
|
||||
.iter()
|
||||
.map(|name| {
|
||||
let mut map = std::collections::HashMap::new();
|
||||
@@ -284,21 +295,21 @@ impl Settings {
|
||||
.collect();
|
||||
config_builder = config_builder.set_override("meta_plugins", meta_plugins)?;
|
||||
}
|
||||
|
||||
|
||||
let config = config_builder.build()?;
|
||||
debug!("CONFIG: Built config, attempting to deserialize");
|
||||
|
||||
|
||||
match config.try_deserialize::<Settings>() {
|
||||
Ok(mut settings) => {
|
||||
debug!("CONFIG: Successfully deserialized settings: {:?}", settings);
|
||||
|
||||
|
||||
// Set defaults for list_format if not provided
|
||||
if settings.list_format.is_empty() {
|
||||
debug!("CONFIG: Setting default list_format");
|
||||
settings.list_format = vec![
|
||||
ColumnConfig {
|
||||
name: "id".to_string(),
|
||||
label: "Item".to_string(),
|
||||
ColumnConfig {
|
||||
name: "id".to_string(),
|
||||
label: "Item".to_string(),
|
||||
align: ColumnAlignment::Right,
|
||||
max_len: None,
|
||||
fg_color: None,
|
||||
@@ -306,9 +317,9 @@ impl Settings {
|
||||
attributes: Vec::new(),
|
||||
padding: None,
|
||||
},
|
||||
ColumnConfig {
|
||||
name: "time".to_string(),
|
||||
label: "Time".to_string(),
|
||||
ColumnConfig {
|
||||
name: "time".to_string(),
|
||||
label: "Time".to_string(),
|
||||
align: ColumnAlignment::Right,
|
||||
max_len: None,
|
||||
fg_color: None,
|
||||
@@ -316,9 +327,9 @@ impl Settings {
|
||||
attributes: Vec::new(),
|
||||
padding: None,
|
||||
},
|
||||
ColumnConfig {
|
||||
name: "size".to_string(),
|
||||
label: "Size".to_string(),
|
||||
ColumnConfig {
|
||||
name: "size".to_string(),
|
||||
label: "Size".to_string(),
|
||||
align: ColumnAlignment::Right,
|
||||
max_len: None,
|
||||
fg_color: None,
|
||||
@@ -326,9 +337,9 @@ impl Settings {
|
||||
attributes: Vec::new(),
|
||||
padding: None,
|
||||
},
|
||||
ColumnConfig {
|
||||
name: "meta:text_line_count".to_string(),
|
||||
label: "Lines".to_string(),
|
||||
ColumnConfig {
|
||||
name: "meta:text_line_count".to_string(),
|
||||
label: "Lines".to_string(),
|
||||
align: ColumnAlignment::Right,
|
||||
max_len: None,
|
||||
fg_color: None,
|
||||
@@ -336,9 +347,9 @@ impl Settings {
|
||||
attributes: Vec::new(),
|
||||
padding: None,
|
||||
},
|
||||
ColumnConfig {
|
||||
name: "tags".to_string(),
|
||||
label: "Tags".to_string(),
|
||||
ColumnConfig {
|
||||
name: "tags".to_string(),
|
||||
label: "Tags".to_string(),
|
||||
align: ColumnAlignment::Left,
|
||||
max_len: None,
|
||||
fg_color: None,
|
||||
@@ -346,9 +357,9 @@ impl Settings {
|
||||
attributes: Vec::new(),
|
||||
padding: None,
|
||||
},
|
||||
ColumnConfig {
|
||||
name: "meta:hostname_short".to_string(),
|
||||
label: "Host".to_string(),
|
||||
ColumnConfig {
|
||||
name: "meta:hostname_short".to_string(),
|
||||
label: "Host".to_string(),
|
||||
align: ColumnAlignment::Left,
|
||||
max_len: None,
|
||||
fg_color: None,
|
||||
@@ -356,9 +367,9 @@ impl Settings {
|
||||
attributes: Vec::new(),
|
||||
padding: None,
|
||||
},
|
||||
ColumnConfig {
|
||||
name: "meta:command".to_string(),
|
||||
label: "Command".to_string(),
|
||||
ColumnConfig {
|
||||
name: "meta:command".to_string(),
|
||||
label: "Command".to_string(),
|
||||
align: ColumnAlignment::Left,
|
||||
max_len: None,
|
||||
fg_color: None,
|
||||
@@ -372,21 +383,19 @@ impl Settings {
|
||||
// Set default meta_plugins to include 'env' if not provided
|
||||
if settings.meta_plugins.is_none() {
|
||||
debug!("CONFIG: Setting default meta_plugins to include 'env'");
|
||||
settings.meta_plugins = Some(vec![
|
||||
MetaPluginConfig {
|
||||
name: "env".to_string(),
|
||||
options: std::collections::HashMap::new(),
|
||||
outputs: std::collections::HashMap::new(),
|
||||
}
|
||||
]);
|
||||
settings.meta_plugins = Some(vec![MetaPluginConfig {
|
||||
name: "env".to_string(),
|
||||
options: std::collections::HashMap::new(),
|
||||
outputs: std::collections::HashMap::new(),
|
||||
}]);
|
||||
}
|
||||
|
||||
|
||||
// Set dir to default if not provided or is empty
|
||||
if settings.dir == PathBuf::new() {
|
||||
debug!("CONFIG: Setting default dir: {:?}", default_dir);
|
||||
settings.dir = default_dir;
|
||||
}
|
||||
|
||||
|
||||
debug!("CONFIG: Final settings: {:?}", settings);
|
||||
Ok(settings)
|
||||
}
|
||||
@@ -398,8 +407,8 @@ impl Settings {
|
||||
}
|
||||
|
||||
pub fn default_dir() -> anyhow::Result<PathBuf> {
|
||||
let mut path = dirs::home_dir()
|
||||
.ok_or_else(|| anyhow::anyhow!("No home directory found"))?;
|
||||
let mut path =
|
||||
dirs::home_dir().ok_or_else(|| anyhow::anyhow!("No home directory found"))?;
|
||||
path.push(".keep");
|
||||
if !path.exists() {
|
||||
std::fs::create_dir_all(&path)?;
|
||||
@@ -419,7 +428,7 @@ impl Settings {
|
||||
.to_string();
|
||||
return Ok(Some(password));
|
||||
}
|
||||
|
||||
|
||||
// Fall back to direct password field
|
||||
if let Some(password) = &server.password {
|
||||
debug!("CONFIG: Using password from config");
|
||||
@@ -428,30 +437,31 @@ impl Settings {
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
|
||||
// Helper methods to access configuration values
|
||||
pub fn server_password(&self) -> Option<String> {
|
||||
self.get_server_password().ok().flatten()
|
||||
}
|
||||
|
||||
|
||||
pub fn server_password_hash(&self) -> Option<String> {
|
||||
self.server.as_ref().and_then(|s| s.password_hash.clone())
|
||||
}
|
||||
|
||||
|
||||
pub fn server_address(&self) -> Option<String> {
|
||||
self.server.as_ref().and_then(|s| s.address.clone())
|
||||
}
|
||||
|
||||
|
||||
pub fn server_port(&self) -> Option<u16> {
|
||||
self.server.as_ref().and_then(|s| s.port)
|
||||
}
|
||||
|
||||
|
||||
pub fn compression(&self) -> Option<String> {
|
||||
self.compression_plugin.as_ref().map(|c| c.name.clone())
|
||||
}
|
||||
|
||||
|
||||
pub fn meta_plugins_names(&self) -> Vec<String> {
|
||||
self.meta_plugins.as_ref()
|
||||
self.meta_plugins
|
||||
.as_ref()
|
||||
.map(|plugins| plugins.iter().map(|p| p.name.clone()).collect())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user