apicurio_cli/commands/
remove.rs1use crate::{config::load_repo_config, constants::APICURIO_CONFIG, identifier::Identifier};
2use anyhow::{anyhow, Result};
3use dialoguer::Select;
4use std::{fs, path::PathBuf};
5
6pub async fn run(identifier_str: String) -> Result<()> {
7 let repo_path = PathBuf::from(APICURIO_CONFIG);
8 let mut repo = load_repo_config(&repo_path)?;
9
10 if repo.dependencies.is_empty() {
11 println!("No dependencies to remove.");
12 return Ok(());
13 }
14
15 let identifier = Identifier::parse(&identifier_str);
17
18 let matches = identifier.find_matches(&repo.dependencies);
20
21 if matches.is_empty() {
22 println!("No dependencies found matching identifier: '{identifier_str}'");
23 println!("Available dependencies:");
24 for dep in &repo.dependencies {
25 println!(
26 " - {} ({}@{})",
27 dep.name,
28 dep.resolved_artifact_id(),
29 dep.version
30 );
31 }
32 return Ok(());
33 }
34
35 let dependency_name = if matches.len() == 1 {
36 matches[0].name.clone()
38 } else {
39 println!("Multiple dependencies match the identifier:");
41 let items: Vec<String> = matches
42 .iter()
43 .map(|dep| {
44 format!(
45 "{} ({}@{} from {})",
46 dep.name,
47 dep.resolved_artifact_id(),
48 dep.version,
49 dep.registry
50 )
51 })
52 .collect();
53
54 let selection = Select::new()
55 .with_prompt("Select dependency to remove")
56 .items(&items)
57 .default(0)
58 .interact()?;
59
60 matches[selection].name.clone()
61 };
62
63 let before_count = repo.dependencies.len();
65 repo.dependencies.retain(|d| d.name != dependency_name);
66
67 if repo.dependencies.len() < before_count {
68 let serialized = serde_yaml::to_string(&repo)?;
69 fs::write(repo_path, serialized)?;
70 println!("✅ Removed dependency: {dependency_name}");
71 } else {
72 return Err(anyhow!("Failed to remove dependency: {}", dependency_name));
73 }
74
75 Ok(())
76}