zoi/project/
environment.rs1use super::{config, executor};
2use crate::utils;
3use anyhow::{Result, anyhow};
4use colored::*;
5use dialoguer::{Select, theme::ColorfulTheme};
6use std::process::Command;
7
8pub fn setup(env_alias: Option<&str>, config: &config::ProjectConfig) -> Result<()> {
9 if config.environments.is_empty() {
10 return Err(anyhow!("No environments defined in zoi.yaml"));
11 }
12
13 let env_to_setup = match env_alias {
14 Some(alias) => config
15 .environments
16 .iter()
17 .find(|e| e.cmd == alias)
18 .ok_or_else(|| anyhow!("Environment '{alias}' not found in zoi.yaml"))?
19 .clone(),
20 None => {
21 let selections: Vec<&str> = config
22 .environments
23 .iter()
24 .map(|e| e.name.as_str())
25 .collect();
26 let selection = Select::with_theme(&ColorfulTheme::default())
27 .with_prompt("Choose an environment to set up")
28 .items(&selections)
29 .default(0)
30 .interact_opt()?
31 .ok_or(anyhow!("No environment chosen."))?;
32
33 config.environments[selection].clone()
34 }
35 };
36
37 println!(
38 "\n--- Setting up environment: {} ---",
39 env_to_setup.name.bold()
40 );
41
42 check_packages(config)?;
43
44 let platform = utils::get_platform()?;
45
46 let run_cmds = match &env_to_setup.run {
47 config::PlatformOrStringVec::StringVec(v) => v.clone(),
48 config::PlatformOrStringVec::Platform(p) => p
49 .get(&platform)
50 .or_else(|| p.get("default"))
51 .cloned()
52 .ok_or_else(|| {
53 anyhow!(
54 "No commands found for platform '{}' and no default specified",
55 platform
56 )
57 })?,
58 };
59
60 let env_vars = match &env_to_setup.env {
61 config::PlatformOrEnvMap::EnvMap(m) => m.clone(),
62 config::PlatformOrEnvMap::Platform(p) => p
63 .get(&platform)
64 .or_else(|| p.get("default"))
65 .cloned()
66 .unwrap_or_default(),
67 };
68
69 for cmd_str in &run_cmds {
70 executor::run_shell_command(cmd_str, &env_vars)?;
71 }
72
73 Ok(())
74}
75
76fn check_packages(config: &config::ProjectConfig) -> Result<()> {
77 if config.packages.is_empty() {
78 return Ok(());
79 }
80 println!("\nChecking required packages...");
81 let mut all_ok = true;
82 for package in &config.packages {
83 print!("- Checking for '{}': ", package.name.cyan());
84 let status = Command::new("bash")
85 .arg("-c")
86 .arg(&package.check)
87 .output()?;
88 if status.status.success() {
89 println!("{}", "OK".green());
90 } else {
91 println!("{}", "MISSING".red());
92 all_ok = false;
93 }
94 }
95 if !all_ok {
96 return Err(anyhow!("One or more required packages are missing."));
97 }
98 Ok(())
99}