use crate::EnvVar;
use crate::Envful;
use colored::*;
use serde_json;
use std::fs;
use std::path::PathBuf;
pub fn check_command(dir: &PathBuf, show_undeclared: bool, silent: bool) {
if !silent {
println!("{}", "Checking env vars...".cyan());
}
let manifest_path = dir.clone().join("envful.json");
let env_file_path = dir.clone().join(".env");
let config: Envful = get_config(&manifest_path);
let given_vars = parse_env_file(&env_file_path)
.iter()
.map(|x| x.name.clone())
.collect::<Vec<String>>();
let missing_vars: Vec<String> = config
.variables
.iter()
.filter(|x| !given_vars.contains(x))
.map(|x| x.clone())
.collect();
let undeclared_vars: Vec<String> = given_vars
.iter()
.filter(|x| !config.variables.contains(x))
.map(|x| x.clone())
.collect();
let error = missing_vars.len() > 0;
if show_undeclared {
if undeclared_vars.len() > 0 {
println!(
"{}",
"Found variables not declared in the manifest:"
.yellow()
.bold()
);
for undeclared_var in undeclared_vars {
println!(
"{} {}",
" Undeclared variable:".yellow(),
undeclared_var.yellow()
);
}
}
}
if error {
eprintln!(
"{}",
"The process is missing environment variables:".red().bold()
);
for missing_var in missing_vars {
eprintln!(
"{} {}",
"❌ Missing variable:".yellow(),
missing_var.yellow()
);
}
std::process::exit(1);
}
if !silent {
println!("{}", "All variables are present ✅".green());
}
}
fn get_config(path: &PathBuf) -> Envful {
let contents = fs::read_to_string(path);
if contents.is_ok() {
let contents = contents.unwrap();
let config: Envful = serde_json::from_str(contents.as_str()).unwrap();
return config;
} else {
eprintln!("Envful manifest not found in {}", path.display());
std::process::exit(1);
}
}
fn parse_env_file(path: &PathBuf) -> Vec<EnvVar> {
let content = fs::read_to_string(path).expect("env file not found");
let lines: Vec<&str> = content.split("\n").collect();
let mut env_vars: Vec<EnvVar> = Vec::new();
for line in lines {
if line.is_empty() {
continue;
}
if line.starts_with("#!") {
let chars = line.split("#!").collect::<Vec<&str>>();
let _description = chars.last().unwrap();
}
if line.starts_with("#") {
continue;
}
let var_string: Vec<String> = line.split("=").map(|x| x.to_string()).collect();
let key = var_string.get(0);
if key.is_none() {
eprintln!("Name is not present");
std::process::exit(1);
}
let key = parse_token(key.unwrap());
let value = var_string.get(1);
if value.is_none() {
eprintln!("Name is not present");
std::process::exit(1);
}
let value = parse_token(value.unwrap());
if value.is_empty() {
eprintln!(
"{}",
format!(
"Value for variable {} is empty, please verify your .env file",
key
)
.red()
.bold()
);
std::process::exit(1);
}
env_vars.push(EnvVar {
name: key,
value: value,
required: true,
default: None,
description: None,
});
}
return env_vars;
}
fn parse_token(text: &String) -> String {
let value = text.clone();
let value = value.trim();
return value.to_string();
}