Initial upload: GitPulse - Developer Productivity Analyzer CLI tool
This commit is contained in:
152
src/config/file.rs
Normal file
152
src/config/file.rs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
use anyhow::{Context, Result};
|
||||||
|
use home::home_dir;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct AnalysisConfig {
|
||||||
|
pub default_time_period: String,
|
||||||
|
pub max_contributors: usize,
|
||||||
|
pub include_merges: bool,
|
||||||
|
pub refactoring_detection: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AnalysisConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
default_time_period: "30 days".to_string(),
|
||||||
|
max_contributors: 50,
|
||||||
|
include_merges: false,
|
||||||
|
refactoring_detection: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct DisplayConfig {
|
||||||
|
pub theme: String,
|
||||||
|
pub chart_height: u16,
|
||||||
|
pub compact_tables: bool,
|
||||||
|
pub show_sparklines: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DisplayConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
theme: "dark".to_string(),
|
||||||
|
chart_height: 10,
|
||||||
|
compact_tables: false,
|
||||||
|
show_sparklines: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ExportConfig {
|
||||||
|
pub default_format: String,
|
||||||
|
pub include_timestamps: bool,
|
||||||
|
pub indent_json: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ExportConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
default_format: "json".to_string(),
|
||||||
|
include_timestamps: true,
|
||||||
|
indent_json: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ColorsConfig {
|
||||||
|
pub primary: String,
|
||||||
|
pub secondary: String,
|
||||||
|
pub accent: String,
|
||||||
|
pub error: String,
|
||||||
|
pub background: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ColorsConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
primary: "blue".to_string(),
|
||||||
|
secondary: "green".to_string(),
|
||||||
|
accent: "yellow".to_string(),
|
||||||
|
error: "red".to_string(),
|
||||||
|
background: "black".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub analysis: AnalysisConfig,
|
||||||
|
pub display: DisplayConfig,
|
||||||
|
pub export: ExportConfig,
|
||||||
|
pub colors: ColorsConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
analysis: AnalysisConfig::default(),
|
||||||
|
display: DisplayConfig::default(),
|
||||||
|
export: ExportConfig::default(),
|
||||||
|
colors: ColorsConfig::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn config_path() -> Result<PathBuf> {
|
||||||
|
let home = home_dir().ok_or_else(|| anyhow::anyhow!("Could not find home directory"))?;
|
||||||
|
let config_dir = home.join(".config").join("gitpulse");
|
||||||
|
Ok(config_dir.join("config.toml"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(custom_path: Option<&PathBuf>) -> Result<Self> {
|
||||||
|
let config_path = if let Some(path) = custom_path {
|
||||||
|
path.clone()
|
||||||
|
} else {
|
||||||
|
Self::config_path()?
|
||||||
|
};
|
||||||
|
|
||||||
|
if !config_path.exists() {
|
||||||
|
return Ok(Self::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = fs::read_to_string(&config_path)
|
||||||
|
.with_context(|| format!("Failed to read config from: {}", config_path.display()))?;
|
||||||
|
|
||||||
|
let config: Config = toml::from_str(&content)
|
||||||
|
.with_context(|| format!("Failed to parse config: {}", config_path.display()))?;
|
||||||
|
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> Result<()> {
|
||||||
|
let config_path = Self::config_path()?;
|
||||||
|
|
||||||
|
if let Some(parent) = config_path.parent() {
|
||||||
|
fs::create_dir_all(parent)
|
||||||
|
.with_context(|| format!("Failed to create config directory: {}", parent.display()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = toml::to_string_pretty(self)
|
||||||
|
.context("Failed to serialize config")?;
|
||||||
|
|
||||||
|
fs::write(&config_path, content)
|
||||||
|
.with_context(|| format!("Failed to write config to: {}", config_path.display()))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn merge(&mut self, other: Config) {
|
||||||
|
self.analysis = other.analysis;
|
||||||
|
self.display = other.display;
|
||||||
|
self.export = other.export;
|
||||||
|
self.colors = other.colors;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user