use std::env;
use clap::Parser;
use crate::engine::CommandResult;
#[derive(Parser)]
#[command(name = "unset", about = "Remove environment variables")]
struct UnsetArgs {
#[arg(required = true)]
names: Vec<String>,
}
pub(super) fn execute(args: &[&str]) -> CommandResult {
let parsed = match super::parse_args::<UnsetArgs>("unset", args) {
Ok(a) => a,
Err(result) => return result,
};
for name in &parsed.names {
unsafe {
env::remove_var(name);
}
}
CommandResult::success(String::new())
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
use std::env;
struct EnvGuard {
key: String,
original: Option<String>,
}
impl EnvGuard {
fn new(key: &str) -> Self {
let original = env::var(key).ok();
Self {
key: key.to_string(),
original,
}
}
}
impl Drop for EnvGuard {
fn drop(&mut self) {
unsafe {
if let Some(ref val) = self.original {
env::set_var(&self.key, val);
} else {
env::remove_var(&self.key);
}
}
}
}
#[test]
#[serial]
fn unset_removes_variable() {
let _guard = EnvGuard::new("JARVISH_TEST_UNSET");
unsafe {
env::set_var("JARVISH_TEST_UNSET", "to_be_removed");
}
assert!(env::var("JARVISH_TEST_UNSET").is_ok());
let result = execute(&["JARVISH_TEST_UNSET"]);
assert_eq!(result.exit_code, 0);
assert!(env::var("JARVISH_TEST_UNSET").is_err());
}
#[test]
#[serial]
fn unset_multiple_variables() {
let _guard1 = EnvGuard::new("JARVISH_TEST_MULTI_A");
let _guard2 = EnvGuard::new("JARVISH_TEST_MULTI_B");
unsafe {
env::set_var("JARVISH_TEST_MULTI_A", "a");
env::set_var("JARVISH_TEST_MULTI_B", "b");
}
let result = execute(&["JARVISH_TEST_MULTI_A", "JARVISH_TEST_MULTI_B"]);
assert_eq!(result.exit_code, 0);
assert!(env::var("JARVISH_TEST_MULTI_A").is_err());
assert!(env::var("JARVISH_TEST_MULTI_B").is_err());
}
#[test]
#[serial]
fn unset_nonexistent_variable_succeeds() {
let _guard = EnvGuard::new("JARVISH_TEST_NONEXISTENT");
unsafe {
env::remove_var("JARVISH_TEST_NONEXISTENT");
}
let result = execute(&["JARVISH_TEST_NONEXISTENT"]);
assert_eq!(result.exit_code, 0);
}
#[test]
fn unset_no_args_returns_error() {
let result = execute(&[]);
assert_ne!(result.exit_code, 0);
}
#[test]
fn unset_help_returns_success() {
let result = execute(&["--help"]);
assert_eq!(result.exit_code, 0);
assert!(result.stdout.contains("unset"));
}
}