#[cfg(target_family = "unix")]
use dirs;
#[cfg(target_family = "unix")]
use std::fs::{File, OpenOptions};
#[cfg(target_family = "unix")]
use std::io::Write;
#[cfg(target_family = "unix")]
use std::path::PathBuf;
use std::env;
use std::env::VarError;
use std::fmt;
use std::io;
#[cfg(target_family = "windows")]
pub fn do_prerequisites() {
use std::fs;
let path = dirs::document_dir();
if let Some(path) = path {
let pkg_version = env!("CARGO_PKG_VERSION");
let template = include_str!("../scripts/profile.ps1").replace("${VER}", pkg_version);
let path = path.join("WindowsPowerShell");
if !path.exists() {
fs::create_dir_all(&path).unwrap();
}
let path = path.join("Profile.ps1");
if !path.exists() {
fs::write(&path, template).unwrap();
} else {
let prefix = "# ----------------------------------VER";
let content = fs::read_to_string(&path).unwrap();
let mut lines = content.lines();
let pos = lines.position(|it| it.starts_with(prefix));
if let Some(pos) = pos {
let content = lines.nth(pos).unwrap().replace(prefix, "");
if content != pkg_version {
fs::write(&path, template).unwrap();
}
} else {
fs::write(&path, template).unwrap();
}
}
return;
}
eprintln!("document path is not exists");
std::process::exit(1);
}
#[cfg(target_os = "windows")]
pub fn inject(it: &str) -> io::Result<()> {
use std::fs;
do_prerequisites();
let profile_path = dirs::document_dir()
.unwrap()
.join("WindowsPowerShell/Profile.ps1");
let content = fs::read_to_string(&profile_path)?;
let mut content_parts: Vec<&str> = content.split("\r\n").collect();
let idx = content_parts
.iter()
.position(|it| it == &"# ----------------------------------SET_ENV_DEFS_END")
.unwrap();
content_parts.insert(idx, it);
fs::write(profile_path, content_parts.join("\r\n"))
}
pub fn check_or_set<T, U>(var: T, value: U) -> io::Result<()>
where
T: fmt::Display + AsRef<std::ffi::OsStr>,
U: fmt::Display,
{
env::var(&var).map(|_| ()).or_else(|_| set(var, value))
}
pub fn get<T: fmt::Display>(var: T) -> io::Result<String> {
env::var(var.to_string()).map_err(|err| match err {
VarError::NotPresent => io::Error::new(io::ErrorKind::NotFound, "Variable not present."),
VarError::NotUnicode(_) => {
io::Error::new(io::ErrorKind::Unsupported, "Encoding not supported.")
}
})
}
#[cfg(target_family = "unix")]
pub fn append<T: fmt::Display>(var: T, value: T) -> io::Result<()> {
let mut profile = get_profile()?;
writeln!(profile, "\nexport {}=\"{}:${}\"", var, value, var)?;
profile.flush()
}
#[cfg(target_os = "windows")]
pub fn append<T: fmt::Display>(var: T, value: T) -> io::Result<()> {
inject(format!("setenv_append {} {}", var, value).as_str())
}
#[cfg(target_family = "unix")]
pub fn prepend<T: fmt::Display>(var: T, value: T) -> io::Result<()> {
let mut profile = get_profile()?;
writeln!(profile, "\nexport {}=\"${}:{}\"", var, value, var)?;
profile.flush()
}
#[cfg(target_os = "windows")]
pub fn prepend<T: fmt::Display>(var: T, value: T) -> io::Result<()> {
inject(format!("setenv_prepend {} {}", var, value).as_str())
}
#[cfg(target_family = "unix")]
pub fn set<T: fmt::Display, U: fmt::Display>(var: T, value: U) -> io::Result<()> {
let mut profile = get_profile()?;
writeln!(profile, "\nexport {}={}", var, value)?;
profile.flush()
}
#[cfg(target_os = "windows")]
pub fn set<T: fmt::Display, U: fmt::Display>(var: T, value: U) -> io::Result<()> {
inject(format!("setenv_set {} {}", var, value).as_str())?;
Ok(())
}
#[cfg(target_family = "unix")]
fn get_profile() -> io::Result<File> {
dirs::home_dir()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "No home directory"))
.and_then(find_profile)
}
#[cfg(target_family = "unix")]
fn find_profile(mut profile: PathBuf) -> io::Result<File> {
profile.push(".bash_profile");
let mut oo = OpenOptions::new();
oo.append(true).create(false);
oo.open(profile.clone())
.or_else(|_| {
profile.pop();
profile.push(".bash_login");
oo.open(profile.clone())
})
.or_else(|_| {
profile.pop();
profile.push(".profile");
oo.open(profile.clone())
})
.or_else(|_| {
profile.pop();
profile.push(".bash_profile");
oo.create(true);
oo.open(profile.clone())
})
}