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}