1use anyhow::{Result, anyhow};
5use colored::Colorize;
6
7use crate::pkg::{db, local, recorder, resolve, types};
8
9pub fn run(
18 package_names: &[String],
19 as_dependency: bool,
20 as_explicit: bool
21) -> Result<()> {
22 let new_reason = if as_dependency {
23 types::InstallReason::Dependency {
24 parent: "manual".to_string()
25 }
26 } else if as_explicit {
27 types::InstallReason::Direct
28 } else {
29 return Err(anyhow!(
30 "Either --as-dependency or --as-explicit must be provided."
31 ));
32 };
33
34 let reason_str = if as_dependency {
35 "dependency".cyan()
36 } else {
37 "explicit".green()
38 };
39
40 for name in package_names {
41 println!("Marking '{}' as {}...", name.blue().bold(), reason_str);
42
43 let request = resolve::parse_source_string(name)?;
44 let (pkg, _, _, _, registry_handle, _, _) =
45 resolve::resolve_package_and_version(name, None, true, false)?;
46 let installed_source = if let Some(sub) = request.sub_package.as_deref()
47 {
48 format!(
49 "#{}@{}/{}:{}",
50 registry_handle.as_deref().unwrap_or("local"),
51 pkg.repo,
52 pkg.name,
53 sub
54 )
55 } else {
56 format!(
57 "#{}@{}/{}",
58 registry_handle.as_deref().unwrap_or("local"),
59 pkg.repo,
60 pkg.name
61 )
62 };
63 let installed_request =
64 resolve::parse_source_string(&installed_source)?;
65 let mut candidates = Vec::new();
66 for scope in [
67 types::Scope::User,
68 types::Scope::System,
69 types::Scope::Project
70 ] {
71 candidates.extend(local::find_installed_manifests_matching(
72 &installed_request,
73 scope
74 )?);
75 }
76
77 let manifest =
78 match crate::cmd::installed_select::choose_installed_manifest(
79 name,
80 &candidates,
81 false
82 ) {
83 Ok(manifest) => manifest,
84 Err(e) => {
85 eprintln!("{}: {}", "Error".red().bold(), e);
86 continue;
87 }
88 };
89 let scope = manifest.scope;
90
91 local::update_manifest_reason(&manifest, new_reason.clone())?;
92
93 let handle = registry_handle
94 .as_deref()
95 .unwrap_or(&manifest.registry_handle);
96 let mut db_pkg = pkg.clone();
97 db_pkg.repo.clone_from(&manifest.repo);
98 db_pkg.scope = manifest.scope;
99 db_pkg.sub_package.clone_from(&manifest.sub_package);
100 if let Ok(conn) = db::open_connection("local") {
101 let _ = db::update_package(
102 &conn,
103 &db_pkg,
104 handle,
105 Some(scope),
106 manifest.sub_package.as_deref(),
107 Some(&new_reason)
108 );
109 }
110
111 let _ = recorder::update_package_reason(&manifest, &new_reason);
112
113 println!(
114 "Successfully marked '{}' as {}.",
115 pkg.name.cyan(),
116 reason_str
117 );
118 }
119
120 Ok(())
121}