zoi_uninstall/
autoremove.rs1use anyhow::Result;
4use colored::Colorize;
5use zoi_core::types::InstallReason;
6use zoi_core::utils as core_utils;
7use zoi_resolver::local;
8
9pub fn run(yes: bool, dry_run: bool) -> Result<()> {
16 println!("Checking for unused dependencies...");
17 let all_installed = local::get_installed_packages()?;
18 let mut packages_to_remove: Vec<String> = Vec::new();
19
20 for package in &all_installed {
21 if !matches!(package.reason, InstallReason::Dependency { .. }) {
22 continue;
23 }
24
25 let package_dir = local::get_package_dir(
26 package.scope,
27 &package.registry_handle,
28 &package.repo,
29 &package.name
30 )?;
31 let dependents = local::get_dependents(&package_dir)?;
32
33 if dependents.is_empty() {
34 packages_to_remove.push(local::installed_manifest_source(package));
35 }
36 }
37
38 if packages_to_remove.is_empty() {
39 println!("{}", "No unused dependencies to remove.".green());
40 return Ok(());
41 }
42
43 if dry_run {
44 println!("\nThe following packages WOULD BE REMOVED (Dry-run):");
45 for pkg_name in &packages_to_remove {
46 println!(" - {}", pkg_name.yellow());
47 }
48 return Ok(());
49 }
50
51 println!("\nThe following packages will be REMOVED:");
52 for pkg_name in &packages_to_remove {
53 println!(" - {}", pkg_name.yellow());
54 }
55
56 if !core_utils::ask_for_confirmation("\nDo you want to continue?", yes) {
57 println!("Operation aborted.");
58 return Ok(());
59 }
60
61 for pkg_name in &packages_to_remove {
62 println!("\n{} Removing {}...", "::".bold().blue(), pkg_name.bold());
63 if let Err(e) = crate::run(pkg_name, None, yes, false, false) {
64 eprintln!(
65 "{} Failed to remove {}: {}",
66 "Error:".red(),
67 pkg_name,
68 e
69 );
70 }
71 }
72
73 Ok(())
74}