Skip to main content

zoi_uninstall/
autoremove.rs

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