zoi_cli/cmd/install/
mod.rs1pub mod args;
3pub mod orchestrator;
5
6use anyhow::Result;
7use colored::Colorize;
8use zoi_project as project;
9
10use crate::pkg::types;
11
12pub fn run(
18 sources: &[String],
19 repo: Option<String>,
20 force: bool,
21 all_optional: bool,
22 yes: bool,
23 scope: Option<crate::cli::InstallScope>,
24 local: bool,
25 global: bool,
26 save: bool,
27 deps_only: bool,
28 build_deps_only: bool,
29 build_type: Option<&str>,
30 dry_run: bool,
31 plugin_manager: Option<&crate::pkg::plugin::PluginManager>,
32 build: bool,
33 frozen: bool,
34 explain: bool,
35 plan_json: bool,
36 retry: u32,
37 verbose: bool,
38 purl: bool,
39 project_config: Option<project::config::ProjectConfig>
40) -> Result<()> {
41 if plan_json && !dry_run {
42 return Err(anyhow::anyhow!("--plan-json requires --dry-run"));
43 }
44 let mut resolved_scope = scope.map(|s| match s {
45 crate::cli::InstallScope::User => types::Scope::User,
46 crate::cli::InstallScope::System => types::Scope::System,
47 crate::cli::InstallScope::Project => types::Scope::Project
48 });
49
50 if local {
51 resolved_scope = Some(types::Scope::Project);
52 } else if global {
53 resolved_scope = Some(types::Scope::User);
54 }
55
56 let scope = resolved_scope
57 .unwrap_or_else(crate::pkg::utils::resolve_fallback_scope);
58
59 let effective_sources: Vec<String> = if build_deps_only {
63 if sources.is_empty() && repo.is_none() {
64 return Err(anyhow::anyhow!(
65 "--build-deps-only requires at least one package source."
66 ));
67 }
68 let platform = zoi_core::utils::get_platform()?;
69 let mut all_build_deps: Vec<String> = Vec::new();
70 for source in sources {
71 let resolved = zoi_resolver::resolve::resolve_source(
72 source,
73 Some(scope),
74 true,
75 yes
76 )?;
77 let deps = crate::pkg::package::build::get_build_dependencies(
78 resolved.path.as_path(),
79 build_type,
80 &platform,
81 None,
82 false
83 )?
84 .unwrap_or_default();
85 println!(
86 "{} Build dependencies for {source}: {}",
87 "::".bold().blue(),
88 if deps.is_empty() {
89 "none".dimmed().to_string()
90 } else {
91 deps.join(", ")
92 }
93 );
94 all_build_deps.extend(deps);
95 }
96 all_build_deps.sort();
97 all_build_deps.dedup();
98 if all_build_deps.is_empty() {
99 println!(
100 "{}",
101 "Nothing to install - no build dependencies found.".green()
102 );
103 return Ok(());
104 }
105 all_build_deps
106 } else {
107 sources.to_vec()
108 };
109
110 let options = orchestrator::InstallOptions {
111 scope,
112 force,
113 all_optional,
114 yes,
115 save,
116 deps_only,
117 build_type,
118 dry_run,
119 plugin_manager,
120 build,
121 frozen,
122 explain,
123 plan_json,
124 retry,
125 verbose,
126 purl,
127 project_config
128 };
129
130 let orchestrator = orchestrator::Orchestrator::new(options);
131 orchestrator.run(&effective_sources, repo)
132}