Skip to main content

zoi_cli/cmd/
mark.rs

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}