Initial upload: DotMigrate dotfiles migration tool with CI/CD
This commit is contained in:
181
src/config/mod.rs
Normal file
181
src/config/mod.rs
Normal file
@@ -0,0 +1,181 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
use crate::cli::SyncBackend;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Dotfile {
|
||||
pub path: PathBuf,
|
||||
pub content_hash: Option<String>,
|
||||
pub permissions: Option<u32>,
|
||||
pub platform: Option<String>,
|
||||
pub template: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub excludes: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for Dotfile {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
path: PathBuf::new(),
|
||||
content_hash: None,
|
||||
permissions: None,
|
||||
platform: None,
|
||||
template: Some(false),
|
||||
excludes: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SyncConfig {
|
||||
pub backend: Option<SyncBackend>,
|
||||
pub remote: Option<String>,
|
||||
pub branch: String,
|
||||
pub path: PathBuf,
|
||||
#[serde(default)]
|
||||
pub excludes: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for SyncConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
backend: Some(SyncBackend::Git),
|
||||
remote: None,
|
||||
branch: "main".to_string(),
|
||||
path: PathBuf::from("dotfiles"),
|
||||
excludes: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MergeConfig {
|
||||
pub strategy: Option<String>,
|
||||
pub keep_backup: bool,
|
||||
pub auto_resolve: bool,
|
||||
}
|
||||
|
||||
impl Default for MergeConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
strategy: Some("ask".to_string()),
|
||||
keep_backup: true,
|
||||
auto_resolve: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DetectConfig {
|
||||
pub patterns: Vec<String>,
|
||||
pub exclude_patterns: Vec<String>,
|
||||
pub include_hidden: bool,
|
||||
pub scan_depth: usize,
|
||||
}
|
||||
|
||||
impl Default for DetectConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
patterns: vec![
|
||||
".*".to_string(),
|
||||
".config/*".to_string(),
|
||||
".local/*".to_string(),
|
||||
],
|
||||
exclude_patterns: vec![
|
||||
".git".to_string(),
|
||||
".gitignore".to_string(),
|
||||
"node_modules".to_string(),
|
||||
".cache".to_string(),
|
||||
],
|
||||
include_hidden: true,
|
||||
scan_depth: 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BackupConfig {
|
||||
pub directory: PathBuf,
|
||||
pub max_backups: usize,
|
||||
pub timestamp_format: String,
|
||||
}
|
||||
|
||||
impl Default for BackupConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
directory: dirs::home_dir()
|
||||
.map(|p| p.join(".dotmigrate/backups"))
|
||||
.unwrap_or_else(|| PathBuf::from(".dotmigrate/backups")),
|
||||
max_backups: 10,
|
||||
timestamp_format: "%Y-%m-%d_%H-%M-%S".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub version: String,
|
||||
pub sync: SyncConfig,
|
||||
pub merge: MergeConfig,
|
||||
pub detect: DetectConfig,
|
||||
pub backup: BackupConfig,
|
||||
#[serde(default)]
|
||||
pub dotfiles: Vec<Dotfile>,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
version: "1.0".to_string(),
|
||||
sync: SyncConfig::default(),
|
||||
merge: MergeConfig::default(),
|
||||
detect: DetectConfig::default(),
|
||||
backup: BackupConfig::default(),
|
||||
dotfiles: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn default_for_backend(backend: SyncBackend) -> Self {
|
||||
let mut config = Self::default();
|
||||
config.sync.backend = Some(backend);
|
||||
config
|
||||
}
|
||||
|
||||
pub fn default_path() -> Result<PathBuf, std::io::Error> {
|
||||
dirs::home_dir()
|
||||
.map(|p| p.join(".dotmigrate/config.yml"))
|
||||
.ok_or_else(|| std::io::Error::new(std::io::ErrorKind::NotFound, "Home directory not found"))
|
||||
}
|
||||
|
||||
pub fn load(path: &Path) -> Result<Self, anyhow::Error> {
|
||||
let content = std::fs::read_to_string(path)?;
|
||||
let config: Config = serde_yaml::from_str(&content)?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn save(&self, path: &Path) -> Result<(), anyhow::Error> {
|
||||
let content = serde_yaml::to_string(self)?;
|
||||
std::fs::write(path, content)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn find_config() -> Option<PathBuf> {
|
||||
let current_dir = std::env::current_dir().ok()?;
|
||||
let home_dir = dirs::home_dir()?;
|
||||
|
||||
for dir in [current_dir, home_dir] {
|
||||
let config_path = dir.join(".dotmigrate/config.yml");
|
||||
if config_path.exists() {
|
||||
return Some(config_path);
|
||||
}
|
||||
let alt_path = dir.join("dotmigrate.yml");
|
||||
if alt_path.exists() {
|
||||
return Some(alt_path);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user