use crate::compression::CompressionConfig;
use anyhow::{Context, Result};
use serde::Deserialize;
use std::fs;
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq, Deserialize)]
pub enum SymlinkBehavior {
#[serde(rename = "preserve")]
Preserve,
#[serde(rename = "dereference")]
Dereference,
#[serde(rename = "skip")]
Skip,
}
impl Default for SymlinkBehavior {
fn default() -> Self {
SymlinkBehavior::Preserve
}
}
#[derive(Debug, Deserialize, Default)]
pub struct Config {
pub threads: Option<usize>,
pub retry_count: Option<u32>,
pub retry_wait: Option<u32>,
pub symlink_behavior: Option<SymlinkBehavior>,
pub compress: Option<bool>,
pub checksum: Option<bool>,
pub purge: Option<bool>,
pub move_files: Option<bool>,
pub exclude_files: Option<Vec<String>>,
pub exclude_dirs: Option<Vec<String>>,
pub block_size: Option<usize>,
pub small_file_threshold: Option<u64>,
pub medium_file_threshold: Option<u64>,
pub large_file_threshold: Option<u64>,
}
pub fn load_config() -> Result<Option<Config>> {
let mut config_paths = vec![
PathBuf::from(".robosync.toml"),
PathBuf::from("robosync.toml"),
];
if let Some(config_dir) = dirs::config_dir() {
config_paths.push(config_dir.join("robosync/robosync.toml"));
}
for path in &config_paths {
if path.exists() {
let contents = fs::read_to_string(path)
.with_context(|| format!("Failed to read config file: {}", path.display()))?;
let config: Config = toml::from_str(&contents)
.with_context(|| format!("Failed to parse config file: {}", path.display()))?;
return Ok(Some(config));
}
}
Ok(None)
}
#[derive(Debug, Clone)]
pub struct SyncOptions {
pub recursive: bool,
pub purge: bool,
pub mirror: bool,
pub dry_run: bool,
pub verbose: u8, pub confirm: bool,
pub show_progress: bool,
pub move_files: bool,
pub exclude_files: Vec<String>,
pub exclude_dirs: Vec<String>,
pub min_size: Option<u64>,
pub max_size: Option<u64>,
pub copy_flags: String,
pub log_file: Option<String>,
pub compress: bool,
pub compression_config: CompressionConfig,
pub show_eta: bool,
pub retry_count: u32,
pub retry_wait: u32,
pub checksum: bool,
#[cfg(target_os = "linux")]
pub linux_optimized: bool,
pub forced_strategy: Option<String>,
pub symlink_behavior: SymlinkBehavior,
pub no_report_errors: bool,
pub debug: bool,
pub small_file_threshold: Option<u64>,
pub medium_file_threshold: Option<u64>,
pub large_file_threshold: Option<u64>,
}
impl Default for SyncOptions {
fn default() -> Self {
Self {
recursive: false,
purge: false,
mirror: false,
dry_run: false,
verbose: 0,
confirm: false,
show_progress: false,
move_files: false,
exclude_files: Vec::new(),
exclude_dirs: Vec::new(),
min_size: None,
max_size: None,
copy_flags: "DAT".to_string(),
log_file: None,
compress: false,
compression_config: CompressionConfig::default(),
show_eta: false,
retry_count: 0,
retry_wait: 30,
checksum: false,
#[cfg(target_os = "linux")]
linux_optimized: false,
forced_strategy: None,
symlink_behavior: SymlinkBehavior::Preserve,
no_report_errors: false,
debug: false,
small_file_threshold: None,
medium_file_threshold: None,
large_file_threshold: None,
}
}
}