pub mod steps;
use std::process::{Command, Stdio};
use serde::{Deserialize, Serialize};
use crate::distro::get_dist;
use self::steps::Steps;
#[derive(Default, Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum Status {
Installed,
#[default] Missing,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Program {
name: String,
installation: Vec<Steps>,
configuration: Vec<Steps>,
dependencies: Vec<Program>,
#[serde(skip)]
status: Status,
#[serde(skip)]
shell: Option<super::cli::Shell>,
}
impl Program {
pub fn get_name(&self) -> String {
self.name.clone()
}
pub fn get_dependencies(&self) -> Vec<Program>{
self.dependencies.clone()
}
pub fn is_installed(&self) -> bool {
self.status == Status::Installed && are_installed(&self.dependencies)
}
pub fn check(&self) -> Status {
let status = Command::new("command")
.arg("-v")
.arg(&self.name)
.stdout(Stdio::null())
.status()
.expect("Failed to execute.");
if status.success() {
Status::Installed
} else {
Status::Missing
}
}
pub fn set_status(&mut self) {
self.status = self.check();
for dep in self.dependencies.iter_mut().by_ref() {
dep.set_status();
}
}
pub fn has_configuration_steps(&self) -> bool {
!self.configuration.is_empty()
}
pub fn has_installation_steps(&self) -> bool {
!self.installation.is_empty()
}
pub fn has_dependencies(&self) -> bool {
!self.dependencies.is_empty()
}
fn execute_for_current_dist(&self, steps: &Vec<Steps>) {
let current_dist = get_dist();
if self.has_installation_steps() {
let installation_steps = steps::steps_for_dist(steps, ¤t_dist);
if let Some(steps) = installation_steps {
steps.execute(&self.shell);
} else {
println!("No installation instructions for '{}' given", current_dist);
}
} else {
println!("No installation instructions for program '{}' given.", self.name);
}
}
pub fn install(&self) {
if self.is_installed() {
println!("{} is already installed", self.name);
return;
}
self.execute_for_current_dist(&self.installation);
}
pub fn configure(&self) {
self.execute_for_current_dist(&self.configuration);
}
pub fn get_status(&self) -> String {
if self.is_installed() {
"Installed".to_owned()
} else {
"Missing".to_owned()
}
}
pub fn get_status_pretty(&self) -> String {
if self.is_installed() {
"🗹 Installed".to_owned()
} else {
"⮽ Missing".to_owned()
}
}
}
pub fn are_installed(programs: &Vec<Program>) -> bool {
if !programs.is_empty() {
for val in programs.clone().iter_mut().map(|d| d.is_installed()) {
if !val {
return false;
}
}
}
true
}
pub fn install_missing(programs: &Vec<Program>) {
for prog in programs.clone() {
prog.install();
if prog.has_dependencies() {
install_missing(&prog.get_dependencies());
}
}
}
pub fn configure_all(programs: &Vec<Program>) {
for prog in programs.clone() {
prog.configure();
if prog.has_dependencies() {
configure_all(&prog.get_dependencies());
}
}
}
pub fn count_missing(programs: &Vec<Program>) -> u8 {
let mut counter = 0;
for program in programs {
if !program.is_installed() {
counter += 1;
}
if program.has_dependencies() {
counter += count_missing(&program.get_dependencies());
}
}
counter
}
pub fn count(programs: &Vec<Program>) -> u8 {
let mut counter = 0;
for program in programs {
counter += 1;
if program.has_dependencies() {
counter += count(&program.get_dependencies());
}
}
counter
}
pub fn print_name(programs: &Vec<Program>) {
for program in programs {
println!("{}", program.get_name());
if program.has_dependencies() {
print_name(&program.get_dependencies());
}
}
}
pub fn print_status(programs: &Vec<Program>) {
for program in programs {
println!("{},{}", program.get_name(), program.get_status());
if program.has_dependencies() {
print_status(&program.get_dependencies());
}
}
}
#[cfg(test)]
mod tests {
use crate::parser::get_programs_from_file;
#[test]
fn test_has_config() {
let programs = get_programs_from_file(&"example.yaml".to_owned());
assert!(programs[0].has_configuration_steps());
}
#[test]
fn test_has_install() {
let programs = get_programs_from_file(&"example.yaml".to_owned());
assert!(programs[0].has_installation_steps());
}
#[test]
fn test_has_dependencies() {
let programs = get_programs_from_file(&"example.yaml".to_owned());
assert!(programs[0].has_dependencies());
}
}