Skip to main content

zoi_cli/cmd/
use_cmd.rs

1//! Command for adding and installing packages to a project or global
2//! configuration.
3
4use std::collections::HashMap;
5
6use anyhow::Result;
7use colored::Colorize;
8
9use crate::pkg::{config, types};
10
11/// Runs the 'use' command.
12///
13/// Adds the specified packages to either the global or project configuration
14/// and triggers an installation.
15///
16/// # Errors
17///
18/// Returns an error if:
19/// - A package name cannot be parsed.
20/// - Configuration update fails.
21/// - The installation process fails.
22/// - In project mode, 'zoi.lua' is missing.
23pub fn run(packages: &[String], global: bool) -> Result<()> {
24    if global {
25        run_global(packages)
26    } else {
27        run_project(packages)
28    }
29}
30
31/// Updates the global configuration with the specified packages and installs
32/// them.
33fn run_global(packages: &[String]) -> Result<()> {
34    println!(
35        "{} Adding packages to global configuration...",
36        "::".bold().blue()
37    );
38
39    let mut versions_to_add = HashMap::new();
40    for pkg_spec in packages {
41        let request = crate::pkg::resolve::parse_source_string(pkg_spec)?;
42        let version =
43            request.version_spec.unwrap_or_else(|| "latest".to_string());
44        versions_to_add.insert(request.name, version);
45    }
46
47    config::update_global_versions(versions_to_add)?;
48
49    println!("{} Installing global packages...", "::".bold().blue());
50    let options = crate::SourceInstallOptions {
51        scope_override: Some(types::Scope::User),
52        yes: true,
53        ..Default::default()
54    };
55
56    crate::install_sources(packages, &options)?;
57
58    println!("\n{}", "Global packages updated and installed.".green());
59    Ok(())
60}
61
62/// Installs project packages, persisting them to 'zoi.yaml' when the project
63/// uses a declarative config, or instructing the user for scriptable 'zoi.lua'
64/// configs whose automatic saving is not supported.
65fn run_project(packages: &[String]) -> Result<()> {
66    if std::path::Path::new("zoi.lua").exists() {
67        println!(
68            "{} Project uses zoi.lua. Automatic saving is not supported for \
69             Lua configurations.",
70            "Note:".yellow().bold()
71        );
72        println!(
73            "   Please add the following to your packages() block in zoi.lua:"
74        );
75        for pkg in packages {
76            println!("   - \"{pkg}\"");
77        }
78    } else {
79        crate::project::config::add_packages_to_config(packages)?;
80    }
81
82    println!("{} Installing project packages...", "::".bold().blue());
83    let options = crate::SourceInstallOptions {
84        scope_override: Some(types::Scope::Project),
85        yes: true,
86        ..Default::default()
87    };
88
89    crate::install_sources(packages, &options)?;
90
91    println!("\n{}", "Project packages updated and installed.".green());
92    Ok(())
93}