use super::{ActionContext, ActionResult, CliAction};
use failure::ResultExt;
use log::error;
use std::ffi::OsString;
use workmn::error::{InvalidProperty, ProjectNotFound};
#[cfg(unix)]
use std::os::unix::process::CommandExt;
pub struct Command {}
impl<'a> CliAction for Command {
fn dispatch(context: ActionContext) -> ActionResult {
let project_name = context.matches.value_of("project").unwrap();
let config = context.unwrap_conf();
let project = config.project(project_name);
if project.is_none() {
return Err(ProjectNotFound::new(&project_name).into());
}
let project = project.unwrap();
let path = project.path();
if path.is_none() {
return Err(InvalidProperty::new(&project_name, "path").into());
}
let path = path.unwrap();
std::env::set_current_dir(&path).context("Switching to project path")?;
let shell = user_shell();
if shell.is_none() {
return Err(failure::err_msg("Could not determine the correct shell"));
}
let shell = shell.unwrap();
let command = std::process::Command::new(shell);
if context.matches.is_present("spawn") {
try_spawn(command)
} else {
try_exec(command)
}
}
}
fn try_spawn(mut command: std::process::Command) -> ActionResult {
match command.status() {
Ok(status) => {
if status.success() {
Ok(())
} else {
Err(failure::err_msg(format!(
"process exited with status code {}",
status
)))
}
}
Err(err) => {
error!("unable to start shell: {}", &err);
Err(err.into())
}
}
}
#[cfg(not(unix))]
use self::try_spawn as try_exec;
#[cfg(unix)]
fn try_exec(mut command: std::process::Command) -> ActionResult {
let error = command.exec();
error!("unable to start shell: {}", error);
Err(error.into())
}
fn user_shell() -> Option<OsString> {
if let Some(shell) = std::env::var_os("SHELL") {
Some(shell)
} else {
None
}
}