use clap::Args;
#[derive(Debug, Clone, Default, Args)]
pub struct ProfileFlags {
#[arg(long = "technology", alias = "tech", value_name = "NAME")]
pub technology: Vec<String>,
#[arg(long)]
pub forge: Option<String>,
#[arg(long)]
pub repo: Option<String>,
#[arg(long, value_name = "MODE")]
pub release_mode: Option<String>,
#[arg(long, value_name = "NAME")]
pub release_driver: Option<String>,
#[arg(long, alias = "style", value_name = "STYLE")]
pub release_style: Option<String>,
#[arg(long, value_name = "BRANCH")]
pub trunk: Option<String>,
#[arg(long, alias = "workflow", value_name = "MODE")]
pub checkout_mode: Option<String>,
#[arg(long, value_name = "MODE")]
pub integration: Option<String>,
#[arg(long, value_name = "FORM")]
pub merge_form: Option<String>,
#[arg(long, value_name = "NAME")]
pub required_check: Option<String>,
#[arg(long, value_name = "NAME")]
pub required_workflow: Option<String>,
}
impl ProfileFlags {
#[must_use]
pub const fn is_empty(&self) -> bool {
self.technology.is_empty()
&& self.forge.is_none()
&& self.repo.is_none()
&& self.release_mode.is_none()
&& self.release_driver.is_none()
&& self.release_style.is_none()
&& self.trunk.is_none()
&& self.checkout_mode.is_none()
&& self.integration.is_none()
&& self.merge_form.is_none()
&& self.required_check.is_none()
&& self.required_workflow.is_none()
}
pub fn inputs(&self) -> Result<crate::profile::Inputs<'_>, crate::error::RkError> {
use crate::landing::{CheckoutMode, Integration, MergeForm, Style};
use crate::profile::ReleaseMode;
Ok(crate::profile::Inputs {
technologies: &self.technology,
forge: self.forge.as_deref(),
repo: self.repo.as_deref(),
release_mode: self
.release_mode
.as_deref()
.map(ReleaseMode::parse)
.transpose()?,
release_driver: self.release_driver.as_deref(),
style: self
.release_style
.as_deref()
.map(Style::parse)
.transpose()?,
trunk: self.trunk.as_deref(),
checkout_mode: self
.checkout_mode
.as_deref()
.map(CheckoutMode::parse)
.transpose()?,
integration: self
.integration
.as_deref()
.map(Integration::parse)
.transpose()?,
merge_form: self
.merge_form
.as_deref()
.map(MergeForm::parse)
.transpose()?,
required_check: self.required_check.as_deref(),
required_workflow: self.required_workflow.as_deref(),
..crate::profile::Inputs::default()
})
}
}
pub const WORKFLOW_ONLY: &str = "--workflow-only";
pub fn workflow_only(
mut inputs: crate::profile::Inputs<'_>,
) -> Result<crate::profile::Inputs<'_>, crate::error::RkError> {
use crate::landing::{CheckoutMode, Integration};
use crate::profile::ReleaseMode;
let mut contradicting: Vec<String> = Vec::new();
if let Some(mode) = inputs
.release_mode
.filter(|mode| *mode != ReleaseMode::None)
{
contradicting.push(format!(
"--release-mode {} (the preset sets profile.release.mode = \"none\")",
mode.as_str()
));
}
if let Some(driver) = inputs.release_driver {
contradicting.push(format!(
"--release-driver {driver} (an automatic release alone takes a driver)"
));
}
if let Some(style) = inputs.style {
contradicting.push(format!(
"--release-style {} (an automatic release alone takes a style)",
style.as_str()
));
}
if let Some(integration) = inputs
.integration
.filter(|integration| *integration != Integration::Local)
{
contradicting.push(format!(
"--integration {} (the preset sets git.integration = \"local\")",
integration.as_str()
));
}
if let Some(mode) = inputs
.checkout_mode
.filter(|mode| *mode != CheckoutMode::LinkedWorktree)
{
contradicting.push(format!(
"--checkout-mode {} (the preset sets git.checkout_mode = \"linked-worktree\")",
mode.as_str()
));
}
if inputs.workflow_guards == Some(false) {
contradicting.push(
"--workflow-guards off (the preset sets capabilities.workflow_guards = true)"
.to_owned(),
);
}
if !contradicting.is_empty() {
return Err(crate::error::RkError::refusal(
crate::diagnostic::Diagnostic::new(
crate::diagnostic::Reason::PresetContradiction,
format!(
"{} contradict{} {WORKFLOW_ONLY}; nothing was written",
contradicting.join(", "),
if contradicting.len() == 1 { "s" } else { "" }
),
)
.expected(format!(
"{WORKFLOW_ONLY} alone, or beside a flag it does not set, such as --merge-form"
))
.action(format!(
"drop {WORKFLOW_ONLY} and state each answer by its own flag, or drop the contradicting flag"
))
.target_state("unchanged"),
));
}
inputs.release_mode = Some(ReleaseMode::None);
inputs.integration = Some(Integration::Local);
inputs.checkout_mode = Some(CheckoutMode::LinkedWorktree);
inputs.workflow_guards = Some(true);
Ok(inputs)
}