Add support for --no-shell option

This commit is contained in:
Chris Aumann 2017-04-06 22:31:52 +02:00
parent 5d5bc4f17b
commit ee5e93e6af
3 changed files with 35 additions and 9 deletions

View File

@ -14,6 +14,7 @@ pub struct Args {
pub restart: bool,
pub debug: bool,
pub run_initially: bool,
pub no_shell: bool,
pub no_vcs_ignore: bool,
pub once: bool,
pub poll: bool,
@ -102,6 +103,10 @@ pub fn get_args() -> Args {
.help("Forces polling mode")
.long("force-poll")
.value_name("interval"))
.arg(Arg::with_name("no-shell")
.help("Do not wrap command in 'sh -c'")
.short("n")
.long("no-shell"))
.arg(Arg::with_name("once").short("1").hidden(true))
.get_matches();
@ -164,6 +169,7 @@ pub fn get_args() -> Args {
restart: args.is_present("restart"),
debug: args.is_present("debug"),
run_initially: !args.is_present("postpone"),
no_shell: args.is_present("no-shell"),
no_vcs_ignore: args.is_present("no-vcs-ignore"),
once: args.is_present("once"),
poll: args.occurrences_of("poll") > 0,

View File

@ -107,7 +107,7 @@ fn main() {
}
let mut guard = child_process.write().unwrap();
*guard = Some(process::spawn(&args.cmd, vec![]));
*guard = Some(process::spawn(&args.cmd, vec![], args.no_shell));
}
loop {
@ -140,7 +140,7 @@ fn main() {
debug!("Launching child process");
{
let mut guard = child_process.write().unwrap();
*guard = Some(process::spawn(&args.cmd, paths));
*guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
}
}
@ -158,7 +158,7 @@ fn main() {
debug!("Launching child process");
{
let mut guard = child_process.write().unwrap();
*guard = Some(process::spawn(&args.cmd, paths));
*guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
}
}
@ -179,7 +179,7 @@ fn main() {
debug!("Launching child process");
{
let mut guard = child_process.write().unwrap();
*guard = Some(process::spawn(&args.cmd, paths));
*guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
}
}
}

View File

@ -1,7 +1,7 @@
use std::path::PathBuf;
pub fn spawn(cmd: &str, updated_paths: Vec<PathBuf>) -> Process {
self::imp::Process::new(cmd, updated_paths).expect("unable to spawn process")
pub fn spawn(cmd: &str, updated_paths: Vec<PathBuf>, no_shell: bool) -> Process {
self::imp::Process::new(cmd, updated_paths, no_shell).expect("unable to spawn process")
}
pub use self::imp::Process;
@ -24,13 +24,33 @@ mod imp {
#[allow(unknown_lints)]
#[allow(mutex_atomic)]
impl Process {
pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
pub fn new(cmd: &str, updated_paths: Vec<PathBuf>, no_shell: bool) -> Result<Process> {
use nix::unistd::*;
use std::io;
use std::os::unix::process::CommandExt;
let mut command = Command::new("sh");
command.arg("-c").arg(cmd);
// Assemble command to run.
// This is either the first argument from cmd (if no_shell was given) or "sh".
// Using "sh -c" gives us features like supportin pipes and redirects,
// but is a little less performant and can cause trouble when using custom signals
// (e.g. --signal SIGHUP)
let mut iter_args = cmd.split_whitespace();
let arg0 = match no_shell {
true => iter_args.next().unwrap(),
false => "sh",
};
// TODO: There might be a better way of doing this with &str.
// I've had to fall back to String, as I wasn't able to join(" ") a Vec<&str>
// into a &str
let args: Vec<String> = match no_shell {
true => iter_args.map(str::to_string).collect(),
false => vec!["-c".to_string(), iter_args.collect::<Vec<&str>>().join(" ")],
};
let mut command = Command::new(arg0);
command.args(args);
debug!("Assembled command {:?}", command);
if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
command.env("WATCHEXEC_UPDATED_PATH", single_path);