algocline_app/service/pkg/
remove.rs1use super::super::alc_toml::{load_alc_toml_document, remove_package_entry, save_alc_toml};
4use super::super::lockfile::{load_lockfile, lockfile_path, save_lockfile};
5use super::super::project::resolve_project_root;
6use super::super::AppService;
7
8impl AppService {
9 pub async fn pkg_remove(
19 &self,
20 name: &str,
21 project_root: Option<String>,
22 version: Option<String>,
23 ) -> Result<String, String> {
24 let root = resolve_project_root(project_root.as_deref()).ok_or_else(|| {
26 format!(
27 "alc.toml not found: cannot remove '{name}' without a project root. \
28 Provide project_root or run from a project directory."
29 )
30 })?;
31
32 match load_alc_toml_document(&root)? {
34 Some(mut doc) => {
35 remove_package_entry(&mut doc, name);
36 save_alc_toml(&root, &doc)?;
37 }
38 None => {
39 return Err(format!("alc.toml not found at {}", root.display()));
40 }
41 }
42
43 let alc_lock_path = lockfile_path(&root);
45 match load_lockfile(&root)? {
46 Some(mut lock) => {
47 let before = lock.packages.len();
48 lock.packages.retain(|p| {
49 if p.name != name {
50 return true; }
52 match &version {
54 Some(v) => p.version.as_deref() != Some(v.as_str()),
55 None => false, }
57 });
58
59 if lock.packages.len() == before {
60 return Err(format!(
61 "Package '{name}' not found in alc.lock at {}",
62 alc_lock_path.display()
63 ));
64 }
65
66 save_lockfile(&root, &lock)?;
67 }
68 None => {
69 return Err(format!(
70 "Package '{name}' not found in alc.lock at {}",
71 alc_lock_path.display()
72 ));
73 }
74 }
75
76 Ok(serde_json::json!({
77 "removed": name,
78 "alc_toml": root.join("alc.toml").display().to_string(),
79 "alc_lock": alc_lock_path.display().to_string(),
80 })
81 .to_string())
82 }
83}