use async_trait::async_trait;
use clap::{Arg, Command, arg};
use cuenv_core::Result;
use cuenv_core::manifest::Base;
use std::path::Path;
use super::super::CommandExecutor;
#[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 ci_provider: Option<String>,
pub update_tools: Option<Vec<String>>,
}
#[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,
}
}
}
#[async_trait]
pub trait SyncProvider: Send + Sync {
fn name(&self) -> &'static str;
fn description(&self) -> &'static str;
async fn sync_path(
&self,
path: &Path,
package: &str,
options: &SyncOptions,
executor: &CommandExecutor,
) -> Result<SyncResult>;
async fn sync_workspace(
&self,
package: &str,
options: &SyncOptions,
executor: &CommandExecutor,
) -> Result<SyncResult>;
fn has_config(&self, manifest: &Base) -> bool;
fn build_command(&self) -> Command {
self.default_command()
}
fn default_command(&self) -> Command {
Command::new(self.name())
.about(self.description())
.arg(arg!(-p --path <PATH> "Path to directory containing CUE files").default_value("."))
.arg(
Arg::new("package")
.long("package")
.help("Name of the CUE package to evaluate")
.default_value("cuenv"),
)
.arg(arg!(--"dry-run" "Show what would be generated without writing files"))
.arg(arg!(--check "Check if files are in sync without making changes"))
.arg(arg!(-A --all "Sync all projects in the workspace"))
}
fn parse_args(&self, matches: &clap::ArgMatches) -> SyncOptions {
let mode = if matches.get_flag("dry-run") {
SyncMode::DryRun
} else if matches.get_flag("check") {
SyncMode::Check
} else {
SyncMode::Write
};
SyncOptions {
mode,
show_diff: matches.get_flag("diff"),
ci_provider: matches.get_one::<String>("provider").cloned(),
update_tools: None,
}
}
}