#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CompatibilityMode {
#[default]
Default,
Strict,
}
pub fn resolve(argv: &[String]) -> CompatibilityMode {
if argv.iter().any(|a| a == "--no-strict") {
return CompatibilityMode::Default;
}
if argv.iter().any(|a| a == "--strict") {
return CompatibilityMode::Strict;
}
if std::env::var("RUSTY_DETOX_STRICT").as_deref() == Ok("1") {
return CompatibilityMode::Strict;
}
if let Some(first) = argv.first() {
let base = basename(first);
if base.eq_ignore_ascii_case("detox") || base.eq_ignore_ascii_case("detox-alias") {
return CompatibilityMode::Strict;
}
}
CompatibilityMode::Default
}
pub fn basename(path: &str) -> &str {
let last = path
.rsplit_once(['/', '\\'])
.map(|(_, b)| b)
.unwrap_or(path);
last.strip_suffix(".exe").unwrap_or(last)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn explicit_strict_flag() {
let argv = vec!["rusty-detox".into(), "--strict".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Strict);
}
#[test]
fn no_strict_overrides() {
let argv = vec![
"rusty-detox".into(),
"--strict".into(),
"--no-strict".into(),
];
assert_eq!(resolve(&argv), CompatibilityMode::Default);
}
#[test]
fn argv0_detox_triggers_strict() {
let argv = vec!["/usr/local/bin/detox".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Strict);
}
#[test]
fn argv0_detox_alias_triggers_strict() {
let argv = vec!["detox-alias".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Strict);
}
#[test]
fn argv0_rusty_detox_is_default() {
let argv = vec!["rusty-detox".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Default);
}
#[test]
fn basename_strips_exe_suffix() {
assert_eq!(basename("C:\\bin\\detox.exe"), "detox");
assert_eq!(basename("/usr/bin/detox"), "detox");
assert_eq!(basename("detox"), "detox");
}
}