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