pub(crate) mod exec;
pub(crate) mod mux;
pub(crate) mod parse;
#[derive(Debug, Clone)]
pub(crate) struct Chain {
pub mode: ChainMode,
pub items: Vec<ChainItem>,
pub failure: FailurePolicy,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum ChainMode {
Sequential,
Parallel,
}
#[derive(Debug, Clone)]
pub(crate) struct ChainItem {
pub kind: ChainItemKind,
pub args: Vec<String>,
}
impl ChainItem {
pub(crate) fn task(name: impl Into<String>) -> Self {
Self {
kind: ChainItemKind::Task(name.into()),
args: Vec::new(),
}
}
pub(crate) const fn install(frozen: bool) -> Self {
Self {
kind: ChainItemKind::Install { frozen },
args: Vec::new(),
}
}
pub(crate) const fn display_name(&self) -> &str {
match &self.kind {
ChainItemKind::Task(name) => name.as_str(),
ChainItemKind::Install { .. } => "install",
}
}
}
#[derive(Debug, Clone)]
pub(crate) enum ChainItemKind {
Task(String),
Install { frozen: bool },
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) enum FailurePolicy {
#[default]
FailFast,
KeepGoing,
KillOnFail,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chain_item_carries_empty_args_in_v1() {
let item = ChainItem::task("build");
assert_eq!(item.args.len(), 0);
assert!(matches!(item.kind, ChainItemKind::Task(ref n) if n == "build"));
}
#[test]
fn install_head_has_no_args() {
let item = ChainItem::install(false);
assert!(item.args.is_empty());
assert!(matches!(
item.kind,
ChainItemKind::Install { frozen: false }
));
}
#[test]
fn install_head_propagates_frozen_flag() {
let item = ChainItem::install(true);
assert!(matches!(item.kind, ChainItemKind::Install { frozen: true }));
}
#[test]
fn failure_policy_default_is_fail_fast() {
assert_eq!(FailurePolicy::default(), FailurePolicy::FailFast);
}
#[test]
fn display_name_is_install_for_install_head() {
assert_eq!(ChainItem::install(false).display_name(), "install");
}
}