use std::env;
use std::fs;
use std::io::{Error, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio};
#[derive(Clone)]
pub struct HaxeVersion(pub String);
impl HaxeVersion {
pub fn get_haxe_installations() -> Result<PathBuf, Error> {
let home: Option<PathBuf> = std::env::home_dir();
if let Some(mut buffer) = home {
buffer.push(".haxe");
return Ok(buffer);
}
Err(Error::new(
ErrorKind::NotFound,
"Home directory not accessible",
))
}
pub fn get_version(path: &str) -> Result<PathBuf, Error> {
let mut buffer: PathBuf = HaxeVersion::get_haxe_installations()?;
buffer.push(path);
Ok(buffer)
}
pub fn get_path(&self) -> Result<PathBuf, Error> {
HaxeVersion::get_version(&self.0)
}
pub fn get_std_path(&self) -> Result<PathBuf, Error> {
let mut buf: PathBuf = self.get_path()?;
buf.push("std");
Ok(buf)
}
pub fn get_path_installed(&self) -> Result<PathBuf, Error> {
if self.get_std_path()?.try_exists()? {
Ok(self.get_path()?)
} else {
Err(Error::new(
ErrorKind::NotFound,
format!(
"Haxe version {} could not be found using the standard library",
self.0
),
))
}
}
}
#[derive(Clone)]
pub struct Config(pub HaxeVersion);
impl Config {
pub fn new(path: Option<&str>) -> Result<Config, Error> {
let version: String = Config::read_from_file(path.unwrap_or(".mask"))?;
Ok(Config(HaxeVersion(version)))
}
pub fn path(config_location: &str) -> Result<&Path, Error> {
let path: &Path = Path::new(config_location);
if path.try_exists()? {
Ok(path)
} else {
Err(Error::new(
ErrorKind::NotFound,
format!("Configuration file \"{}\" does not exist", path.display()),
))
}
}
pub fn read_from_file(supposed_path: &str) -> Result<String, Error> {
match Config::path(supposed_path) {
Ok(path) => {
let mut contents: String = fs::read_to_string(path)?;
contents.retain(|c| c != '\n');
Ok(contents)
}
Err(e) => Err(e),
}
}
pub fn write(path: Option<&str>, version: &str) -> Result<(), Error> {
fs::write(path.unwrap_or(".mask"), version)?;
Ok(())
}
pub fn safe_write(path: Option<&str>, version: &str) -> Result<(), Error> {
if HaxeVersion::get_version(version)?.try_exists()? {
Config::write(path, version)
} else {
Err(Error::new(
ErrorKind::NotFound,
format!("Haxe version {} doesn't exist", version),
))
}
}
}
#[cfg(debug_assertions)]
impl Default for Config {
fn default() -> Config {
Config(HaxeVersion("4.3.7".to_string()))
}
}
pub fn create_patched_cmd(
args: Vec<String>,
config: Config,
prog: PathBuf,
) -> Result<Command, Error> {
let mut cmd: Command = Command::new(prog);
let path: PathBuf = config.0.get_path()?;
cmd.args(args).env(
"PATH",
if cfg!(windows) {
format!(
"{};{}",
path.display(),
env::var("PATH").unwrap_or("".to_string())
)
} else {
format!(
"{}:{}",
path.display(),
env::var("PATH").unwrap_or("".to_string())
)
},
);
Ok(cmd)
}
pub fn haxe_exec(args: Vec<String>, config: Config, prog: Option<String>) -> Result<Output, Error> {
match config.0.get_path_installed() {
Ok(buf) => {
let mut prog_buf: PathBuf = buf.clone();
prog_buf.push(prog.unwrap_or("haxe".to_string()));
if !prog_buf.try_exists()? {
Err(Error::new(
ErrorKind::NotFound,
format!(
"Program at file location \"{}\" does not exist",
prog_buf.display()
),
))
} else {
create_patched_cmd(args, config, prog_buf)?
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
}
}
Err(e) => Err(e),
}
}