use std::{
fs,
process::{Command, Stdio},
};
use anyhow::Error;
use envhub_types::configuration::{self, Configuration};
use indexmap::IndexMap;
use crate::{nix, HOME_MANAGER};
pub fn switch_env(dir: Option<&str>, config: &Configuration, backup: bool) -> Result<(), Error> {
nix::install()?;
let home_nix = fs::read_to_string(format!("{}/home.nix", dir.unwrap_or(HOME_MANAGER)))?;
let mut updated_home_nix = home_nix.clone();
match &config.package_manager {
Some(pm) => {
if pm == "nix" {
updated_home_nix =
add_packages(&home_nix, config.packages.clone().unwrap_or_default())?
}
}
None => {
updated_home_nix = add_packages(&home_nix, config.packages.clone().unwrap_or_default())?
}
};
match &config.symlink_manager {
Some(sm) => {
if sm == "home-manager" {
updated_home_nix =
add_files(&updated_home_nix, config.files.clone().unwrap_or_default())?;
if config.envs.is_some() {
updated_home_nix =
add_envs(&updated_home_nix, config.envs.clone().unwrap_or_default())?;
}
}
}
None => {
updated_home_nix =
add_files(&updated_home_nix, config.files.clone().unwrap_or_default())?;
if config.envs.is_some() {
updated_home_nix =
add_envs(&updated_home_nix, config.envs.clone().unwrap_or_default())?;
}
}
}
let home_nix_file = format!("{}/home.nix", dir.unwrap_or(HOME_MANAGER));
fs::write(&home_nix_file, &updated_home_nix)?;
let cmd = match backup {
true => format!(
"nix run home-manager/master -- switch --flake {} -b backup",
dir.unwrap_or(HOME_MANAGER)
),
false => format!(
"nix run home-manager/master -- switch --flake {}",
dir.unwrap_or(HOME_MANAGER)
),
};
let mut child = Command::new("sh")
.arg("-c")
.arg(cmd)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()?;
child.wait()?;
Ok(())
}
pub fn add_packages(content: &str, pkgs: Vec<String>) -> Result<String, Error> {
let mut packages = nix_editor::read::readvalue(content, "home.packages")?;
let mut entry = String::new();
for pkg in pkgs {
let pkg = match pkg.starts_with("pkgs.") {
true => pkg.to_string(),
false => format!("pkgs.{}", pkg),
};
if packages.contains(&pkg) && !packages.contains(&format!("# {}", pkg)) {
continue;
}
entry.push_str(&format!("\n {}", pkg));
}
entry.push_str("\n]");
packages = packages.replace("\n]", &entry);
packages = packages.replace("\n", "\n ");
let output = nix_editor::write::write(content, "home.packages", &packages)?;
Ok(output)
}
pub fn add_files(
content: &str,
files: IndexMap<String, configuration::File>,
) -> Result<String, Error> {
let mut entry = String::new();
if files.is_empty() {
return Ok(content.into());
}
entry.push_str("{\n");
for (file, config) in files {
if config.source.is_some() {
let source = config.source.unwrap();
let source = match source.starts_with("dotfiles/") {
true => source.to_string(),
false => format!("dotfiles/{}", source),
};
entry.push_str(&format!(" \"{}\".source = {};\n", file, source));
continue;
}
if config.content.is_some() {
entry.push_str(&format!(
" \"{}\".text = ''\n{}\n'';\n",
file,
config.content.unwrap()
));
}
}
entry.push_str("}\n");
let result = nix_editor::write::write(content, "home.file", &entry)?;
Ok(result)
}
pub fn add_envs(content: &str, envs: IndexMap<String, String>) -> Result<String, Error> {
let mut entry = String::new();
if envs.is_empty() {
return Ok(content.into());
}
entry.push_str("{\n");
for (env, value) in envs {
entry.push_str(&format!(" \"{}\" = \"{}\";\n", env, value));
}
entry.push_str("}\n");
let result = nix_editor::write::write(content, "home.sessionVariables", &entry)?;
Ok(result)
}