Skip to content

Commit

Permalink
feat(exec): new subcommand for single command execution
Browse files Browse the repository at this point in the history
  • Loading branch information
Joxit committed Oct 14, 2020
1 parent 38178e6 commit a7c42a5
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 4 deletions.
118 changes: 118 additions & 0 deletions src/commands/exec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use crate::config::{Config, WhenNotify};
use crate::utils::traits::CommandConfig;
use libc::{fork, signal};
use libc::{SIGHUP, SIG_IGN};
use std::fs;
use std::path::PathBuf;
use std::process::{exit, Command, Stdio};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
pub struct Exec {
/// Configuration path (YAML)
#[structopt(long = "config", short = "c")]
config: Option<PathBuf>,
/// Exec the command in background
#[structopt(long = "background", short = "b")]
background: bool,
/// Command to execute
#[structopt()]
command: Vec<String>,
}

impl Exec {
pub fn exec(&self) {
if let Some(config) = &self.config {
if !config.exists() {
eprintln!("The config file {} does not exists", config.display());
return;
}
}

if self.command.is_empty() {
let clap = crate::ApplicationArguments::clap();
let args = format!("{} exec --help", clap.get_name());
clap.get_matches_from(args.split(" "));
}

if self.background && unsafe { fork() } != 0 {
// The main process should return
return;
} else if self.background {
// Ignoring SIGHUP in background mode
unsafe { signal(SIGHUP, SIG_IGN) };
}

if let Err(e) = self.run() {
eprintln!("{}", e);
exit(1);
}
}

fn run(&self) -> Result<(), String> {
let config = if let Some(config) = &self.config {
let yaml = fs::read_to_string(config.as_path())
.map_err(|msg| format!("Can't read the config file: {}", msg))?;

Config::from_str(yaml.as_str())
.map_err(|msg| format!("Can't process the config file: {}", msg))?
} else {
Config::default()
};

let cmd_line = self.command.join(" ");

let mut child = Command::new("sh")
.arg("-c")
.arg(cmd_line.clone())
.stdin(self.stdin())
.stdout_opt(config.stdout(), !self.background)?
.stderr_opt(config.stderr(), !self.background)?
.working_dir(config.working_dir())?
.spawn()
.map_err(|msg| format!("Can't run command `{}`: {}", cmd_line, msg))?;

if let Ok(exit) = child.wait() {
let msg = format!(
"Command `{}` ended with status code {}",
self.command[0], exit
);
self.notify(&config, msg, WhenNotify::End);
} else {
let msg = format!("Command `{}` ended with failure", self.command[0]);
self.notify(&config, msg, WhenNotify::End);
}

Ok(())
}

fn notify(&self, config: &Config, msg: String, when: WhenNotify) {
if let Some(notification) = config.notification() {
if *notification.when() == WhenNotify::Never
|| (*notification.when() != WhenNotify::Always && *notification.when() != when)
{
return;
}
if let Some(slack) = notification.slack() {
if let Some(when_slack) = slack.when() {
if *when_slack == WhenNotify::Never
|| (*when_slack != WhenNotify::Always && *when_slack != when)
{
return;
}
}
if let Err(e) = crate::notification::post_slack(&slack, msg.as_str()) {
eprintln!("Can't use slac notification: {}", e);
}
}
}
}

fn stdin(&self) -> Stdio {
if self.background {
Stdio::null()
} else {
Stdio::inherit()
}
}
}
10 changes: 8 additions & 2 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::commands::run::Run;
use crate::commands::dot::Dot;
use crate::commands::exec::Exec;
use crate::commands::run::Run;
use structopt::StructOpt;

mod run;
mod dot;
mod exec;
mod run;

#[derive(Debug, StructOpt)]
pub enum Command {
Expand All @@ -13,12 +15,16 @@ pub enum Command {
/// Export the configuration to a graph (needs graphviz/dot).
#[structopt(name = "dot")]
Dot(Dot),
/// Execute a single command with notification.
#[structopt(name = "exec")]
Exec(Exec),
}

impl Command {
pub fn exec(&self) {
match self {
Command::Run(executable) => executable.exec(),
Command::Exec(executable) => executable.exec(),
Command::Dot(executable) => executable.exec(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/run.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::utils::traits::CommandConfig;
use crate::config::{Config, WhenNotify};
use crate::fst::*;
use crate::utils::traits::CommandConfig;
use libc::{fork, signal};
use libc::{SIGHUP, SIG_IGN};
use std::fs;
Expand Down
2 changes: 1 addition & 1 deletion src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use yaml_rust::YamlLoader;
mod task;
mod yaml_trait;

#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Clone, Default)]
pub struct Config {
tasks: HashMap<String, Task>,
concurrency: i64,
Expand Down

0 comments on commit a7c42a5

Please sign in to comment.