use crate::local_store::LocalStore;
use eyre::{OptionExt, bail};
use std::fs;
#[derive(Debug)]
pub struct DeleteArgs {
component_ref: String,
force: bool,
}
impl DeleteArgs {
pub fn parse(args: impl Iterator<Item = String>) -> eyre::Result<Self> {
let mut component_ref: Option<String> = None;
let mut force = false;
for arg in args {
match arg.as_str() {
"--force" | "-f" | "-y" | "--yes" => {
force = true;
}
"--help" | "-h" | "help" => {
print_help();
std::process::exit(0);
}
other => {
if other.starts_with('-') {
bail!("unknown flag: {}", other);
}
if component_ref.is_some() {
bail!("unexpected argument: {}", other);
}
component_ref = Some(other.to_string());
}
}
}
let component_ref = component_ref.ok_or_eyre(
"missing component reference\n\n\
Usage: asterai component delete <namespace:name>\n\
Example: asterai component delete myteam:my-component",
)?;
Ok(Self {
component_ref,
force,
})
}
pub fn execute(&self) -> eyre::Result<()> {
let (namespace, name) = parse_component_reference(&self.component_ref)?;
let versions_to_delete: Vec<_> = LocalStore::find_all_versions(&namespace, &name)
.into_iter()
.filter(|path| {
path.join("component.wasm").exists() || path.join("package.wasm").exists()
})
.collect();
if versions_to_delete.is_empty() {
bail!("component '{}:{}' not found locally", namespace, name);
}
if !self.force {
println!(
"WARNING: This will delete {} local version(s) of component '{}:{}'.",
versions_to_delete.len(),
namespace,
name
);
print!("Type the component name to confirm: ");
std::io::Write::flush(&mut std::io::stdout())?;
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
let input = input.trim();
if input != name {
bail!("confirmation failed: expected '{}', got '{}'", name, input);
}
}
for path in &versions_to_delete {
let version = path
.file_name()
.and_then(|s| s.to_str())
.unwrap_or("unknown");
fs::remove_dir_all(path)?;
println!("deleted {}", version);
}
println!(
"deleted {} version(s) of {}:{}",
versions_to_delete.len(),
namespace,
name
);
Ok(())
}
}
fn parse_component_reference(s: &str) -> eyre::Result<(String, String)> {
let (namespace, name) = s
.split_once(':')
.or_else(|| s.split_once('/'))
.ok_or_else(|| eyre::eyre!("invalid component reference '{}': use namespace:name", s))?;
Ok((namespace.to_string(), name.to_string()))
}
fn print_help() {
println!(
r#"Delete a component locally.
Usage: asterai component delete <namespace:name> [options]
Arguments:
<namespace:name> Component to delete
Options:
-f, --force, -y Skip confirmation prompt
-h, --help Show this help message
Examples:
asterai component delete myteam:my-component
asterai component delete myteam:my-component --force
"#
);
}