use crate::Result;
use crate::manifest::Base;
use crate::module::ModuleEvaluation;
use async_trait::async_trait;
use std::path::Path;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub enum SyncMode {
#[default]
Write,
DryRun,
Check,
}
#[derive(Debug, Clone, Default)]
pub struct SyncOptions {
pub mode: SyncMode,
pub show_diff: bool,
pub force: bool,
}
#[derive(Debug, Clone)]
pub struct SyncResult {
pub output: String,
pub had_error: bool,
}
impl SyncResult {
#[must_use]
pub fn success(output: impl Into<String>) -> Self {
Self {
output: output.into(),
had_error: false,
}
}
#[must_use]
pub fn error(output: impl Into<String>) -> Self {
Self {
output: output.into(),
had_error: true,
}
}
#[must_use]
pub fn empty() -> Self {
Self {
output: String::new(),
had_error: false,
}
}
}
pub struct SyncContext<'a> {
pub module: &'a ModuleEvaluation,
pub options: &'a SyncOptions,
pub package: &'a str,
}
#[async_trait]
pub trait SyncProvider: Send + Sync {
fn name(&self) -> &'static str;
fn description(&self) -> &'static str;
fn has_config(&self, manifest: &Base) -> bool;
async fn sync_path(&self, path: &Path, ctx: &SyncContext<'_>) -> Result<SyncResult>;
async fn sync_all(&self, ctx: &SyncContext<'_>) -> Result<SyncResult>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sync_result_success() {
let result = SyncResult::success("Created .gitignore");
assert_eq!(result.output, "Created .gitignore");
assert!(!result.had_error);
}
#[test]
fn test_sync_result_error() {
let result = SyncResult::error("Failed to write file");
assert_eq!(result.output, "Failed to write file");
assert!(result.had_error);
}
#[test]
fn test_sync_result_empty() {
let result = SyncResult::empty();
assert!(result.output.is_empty());
assert!(!result.had_error);
}
#[test]
fn test_sync_options_default() {
let options = SyncOptions::default();
assert_eq!(options.mode, SyncMode::Write);
assert!(!options.show_diff);
assert!(!options.force);
}
#[test]
fn test_sync_mode_default() {
assert_eq!(SyncMode::default(), SyncMode::Write);
}
}