use zeph_core::config::Config;
use crate::cli::Cli;
#[derive(Clone, Copy, Debug, Default)]
#[allow(clippy::struct_excessive_bools)] pub(crate) struct ExecutionMode {
pub(crate) bare: bool,
pub(crate) safe_mode: bool,
pub(crate) json: bool,
pub(crate) auto: bool,
}
impl ExecutionMode {
pub(crate) fn from_cli_and_config(cli: &Cli, cfg: &Config) -> Self {
Self {
bare: cli.bare || cfg.cli.bare,
safe_mode: cli.safe_mode || cfg.cli.safe_mode,
json: cli.json || cfg.cli.json,
auto: cli.auto || cfg.cli.auto,
}
}
}
pub(crate) fn resolve_safe_mode_flag(cli_flag: bool) -> bool {
cli_flag
|| std::env::var("ZEPH_SAFE_MODE")
.ok()
.and_then(|v| v.parse::<bool>().ok())
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
fn default_cli() -> Cli {
Cli::default()
}
#[test]
fn all_false_by_default() {
let mode = ExecutionMode::default();
assert!(!mode.bare && !mode.safe_mode && !mode.json && !mode.auto);
}
#[test]
fn cli_bare_flag_activates_bare() {
let mut cli = default_cli();
cli.bare = true;
let mode = ExecutionMode::from_cli_and_config(&cli, &Config::default());
assert!(mode.bare);
assert!(!mode.safe_mode);
assert!(!mode.json);
assert!(!mode.auto);
}
#[test]
fn cli_safe_mode_flag_activates_safe_mode() {
let mut cli = default_cli();
cli.safe_mode = true;
let mode = ExecutionMode::from_cli_and_config(&cli, &Config::default());
assert!(mode.safe_mode);
assert!(!mode.bare);
}
#[test]
fn config_safe_mode_activates_safe_mode() {
let mut cfg = Config::default();
cfg.cli.safe_mode = true;
let mode = ExecutionMode::from_cli_and_config(&default_cli(), &cfg);
assert!(mode.safe_mode);
assert!(!mode.bare);
}
#[test]
fn bare_and_safe_mode_compose_independently() {
let mut cli = default_cli();
cli.bare = true;
cli.safe_mode = true;
let mode = ExecutionMode::from_cli_and_config(&cli, &Config::default());
assert!(mode.bare);
assert!(mode.safe_mode);
}
#[test]
fn resolve_safe_mode_flag_true_short_circuits_env_read() {
assert!(resolve_safe_mode_flag(true));
}
#[test]
#[serial_test::serial(zeph_safe_mode_env)]
#[allow(unsafe_code)]
fn resolve_safe_mode_flag_reads_env_when_flag_false() {
unsafe {
std::env::set_var("ZEPH_SAFE_MODE", "true");
}
assert!(resolve_safe_mode_flag(false));
unsafe {
std::env::remove_var("ZEPH_SAFE_MODE");
}
assert!(!resolve_safe_mode_flag(false));
}
#[test]
fn cli_json_flag_activates_json() {
let mut cli = default_cli();
cli.json = true;
let mode = ExecutionMode::from_cli_and_config(&cli, &Config::default());
assert!(mode.json);
assert!(!mode.bare);
}
#[test]
fn cli_auto_flag_activates_auto() {
let mut cli = default_cli();
cli.auto = true;
let mode = ExecutionMode::from_cli_and_config(&cli, &Config::default());
assert!(mode.auto);
}
#[test]
fn config_bare_activates_bare_mode() {
let mut cfg = Config::default();
cfg.cli.bare = true;
let mode = ExecutionMode::from_cli_and_config(&default_cli(), &cfg);
assert!(mode.bare);
assert!(!mode.json);
}
#[test]
fn config_json_activates_json_mode() {
let mut cfg = Config::default();
cfg.cli.json = true;
let mode = ExecutionMode::from_cli_and_config(&default_cli(), &cfg);
assert!(mode.json);
}
#[test]
fn config_auto_activates_auto_mode() {
let mut cfg = Config::default();
cfg.cli.auto = true;
let mode = ExecutionMode::from_cli_and_config(&default_cli(), &cfg);
assert!(mode.auto);
}
#[test]
fn cli_overrides_config_when_both_false_still_false() {
let mode = ExecutionMode::from_cli_and_config(&default_cli(), &Config::default());
assert!(!mode.bare && !mode.safe_mode && !mode.json && !mode.auto);
}
}