Skip to main content

zoi_cli/cmd/
why.rs

1use crate::pkg::{local, resolve, types};
2use anyhow::{Result, anyhow};
3use colored::*;
4
5pub fn run(package_name: &str) -> Result<()> {
6    let request = resolve::parse_source_string(package_name)?;
7    let mut candidates = Vec::new();
8    for scope in [
9        types::Scope::User,
10        types::Scope::System,
11        types::Scope::Project,
12    ] {
13        candidates.extend(local::find_installed_manifests_matching(&request, scope)?);
14    }
15    if candidates.is_empty() {
16        return Err(anyhow!("Package '{}' is not installed.", package_name));
17    }
18    let manifest =
19        crate::cmd::installed_select::choose_installed_manifest(package_name, &candidates, false)?;
20
21    let pkg_dir = local::get_package_dir(
22        manifest.scope,
23        &manifest.registry_handle,
24        &manifest.repo,
25        &manifest.name,
26    )?;
27    let mut reasons = Vec::new();
28
29    if manifest.reason == types::InstallReason::Direct {
30        reasons.push("it was installed directly by the user".to_string());
31    }
32
33    let mut dependents = local::get_dependents(&pkg_dir)?;
34
35    if !dependents.is_empty() {
36        dependents.sort();
37        reasons.push(format!(
38            "it is a dependency for: {}",
39            dependents.join(", ").cyan()
40        ));
41    }
42
43    if reasons.is_empty() {
44        if matches!(manifest.reason, types::InstallReason::Dependency { .. }) {
45            println!(
46                "Package '{}' is installed as a dependency, but no packages list it as a requirement. It may be an orphan.",
47                local::installed_manifest_source(&manifest).bold()
48            );
49        } else {
50            println!(
51                "Package '{}' is installed, but its installation reason is unclear.",
52                local::installed_manifest_source(&manifest).bold()
53            );
54        }
55    } else {
56        println!(
57            "Package '{}' is installed because {}.",
58            local::installed_manifest_source(&manifest).bold(),
59            reasons.join(" and ")
60        );
61    }
62
63    Ok(())
64}