use super::error::*;
use super::PierResult;
use serde::{Deserialize, Serialize};
use snafu::ResultExt;
use std::fs::File;
use std::io::prelude::*;
use std::os::unix::fs::PermissionsExt;
use std::process::{Command, Output, Stdio};
use tempfile;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Script {
#[serde(skip)]
pub alias: String,
pub command: String,
pub description: Option<String>,
pub reference: Option<String>,
pub tags: Option<Vec<String>>,
}
impl Script {
pub fn has_shebang(&self) -> bool {
match self.command.lines().nth(0) {
Some(line) => line.starts_with("#!"),
None => false,
}
}
pub fn display_command(&self, display_full: bool, width: usize) -> &str {
match display_full {
true => &self.command,
false => {
match &self.command.lines().nth(0) {
Some(line) => {
match line.chars().count() {
c if c <= width => line,
c if c > width => &line[0..width],
_ => "",
}
}
None => &self.command,
}
}
}
}
pub fn run_with_cli_interpreter(
&self,
interpreter: &Vec<String>,
args: Vec<String>,
) -> PierResult<Output> {
let cmd = Command::new(&interpreter[0])
.args(&interpreter[1..])
.arg(&self.command)
.arg(&self.alias)
.args(&args)
.stderr(Stdio::piped())
.spawn()
.context(CommandExec)?
.wait_with_output()
.context(CommandExec)?;
Ok(cmd)
}
pub fn run_with_shebang(&self, args: Vec<String>) -> PierResult<Output> {
let tmpdir = tempfile::Builder::new()
.prefix("pier")
.tempdir()
.context(ExecutableTempFileCreate)?;
let exec_file_path = tmpdir.path().join(&self.alias);
{
let mut exec_file = File::create(&exec_file_path).context(ExecutableTempFileCreate)?;
exec_file
.write(self.command.as_bytes())
.context(ExecutableTempFileCreate)?;
let mut permissions = exec_file
.metadata()
.context(ExecutableTempFileCreate)?
.permissions();
permissions.set_mode(0o500);
exec_file
.set_permissions(permissions)
.context(ExecutableTempFileCreate)?;
}
let cmd = Command::new(exec_file_path)
.stderr(Stdio::piped())
.args(&args)
.spawn()
.context(CommandExec)?
.wait_with_output()
.context(CommandExec)?;
Ok(cmd)
}
}