use std::fs;
use clap::Args;
use super::install::{alias_candidates, is_generated_alias};
use crate::ui;
#[derive(Debug, Args)]
pub struct UninstallArgs {
#[arg(required = true)]
pub names: Vec<String>,
}
pub async fn run(args: UninstallArgs) -> anyhow::Result<()> {
let backend = microsandbox::backend::default_backend();
let home = match backend.as_local() {
Some(local) => local.config().home(),
None => microsandbox_utils::resolve_home(),
};
let bin_dir = home.join("bin");
let mut failed = false;
for name in &args.names {
if name.contains('/') || name.contains('\\') || name.contains(':') || name.contains("..") {
ui::error(&format!("invalid alias name '{name}'"));
failed = true;
continue;
}
let Some(path) = alias_candidates(&bin_dir, name)
.into_iter()
.find(|path| path.exists())
else {
ui::error(&format!("alias '{name}' not found"));
failed = true;
continue;
};
let content = match fs::read_to_string(&path) {
Ok(c) => c,
Err(e) => {
ui::error(&format!("failed to read '{name}': {e}"));
failed = true;
continue;
}
};
if !is_generated_alias(&content) {
ui::error(&format!("'{name}' is not an msb-installed alias"));
failed = true;
continue;
}
match fs::remove_file(&path) {
Ok(()) => ui::success("Uninstalled", name),
Err(e) => {
ui::error(&format!("failed to remove '{name}': {e}"));
failed = true;
}
}
}
if failed {
anyhow::bail!("some aliases failed to uninstall");
}
Ok(())
}