From 5f0008040e9a168e5eaec0bbd754a6f14d12896a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 Apr 2020 15:14:55 +0200 Subject: Allow to set env vars and pipe stdin via not_bash --- xtask/src/not_bash.rs | 60 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 11 deletions(-) (limited to 'xtask/src/not_bash.rs') diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs index ef1699934..a6431e586 100644 --- a/xtask/src/not_bash.rs +++ b/xtask/src/not_bash.rs @@ -3,6 +3,8 @@ use std::{ cell::RefCell, env, + ffi::OsString, + io::Write, path::{Path, PathBuf}, process::{Command, Stdio}, }; @@ -57,7 +59,10 @@ macro_rules! _run { run!($($expr),*; echo = true) }; ($($expr:expr),* ; echo = $echo:expr) => { - $crate::not_bash::run_process(format!($($expr),*), $echo) + $crate::not_bash::run_process(format!($($expr),*), $echo, None) + }; + ($($expr:expr),* ; <$stdin:expr) => { + $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin)) }; } pub(crate) use _run as run; @@ -77,6 +82,21 @@ impl Drop for Pushd { } } +pub struct Pushenv { + _p: (), +} + +pub fn pushenv(var: &str, value: &str) -> Pushenv { + Env::with(|env| env.pushenv(var.into(), value.into())); + Pushenv { _p: () } +} + +impl Drop for Pushenv { + fn drop(&mut self) { + Env::with(|env| env.popenv()) + } +} + pub fn rm_rf(path: impl AsRef) -> Result<()> { let path = path.as_ref(); if !path.exists() { @@ -90,15 +110,15 @@ pub fn rm_rf(path: impl AsRef) -> Result<()> { } #[doc(hidden)] -pub fn run_process(cmd: String, echo: bool) -> Result { - run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd)) +pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result { + run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd)) } pub fn date_iso() -> Result { run!("date --iso --utc") } -fn run_process_inner(cmd: &str, echo: bool) -> Result { +fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result { let mut args = shelx(cmd); let binary = args.remove(0); let current_dir = Env::with(|it| it.cwd().to_path_buf()); @@ -107,12 +127,17 @@ fn run_process_inner(cmd: &str, echo: bool) -> Result { println!("> {}", cmd) } - let output = Command::new(binary) - .args(args) - .current_dir(current_dir) - .stdin(Stdio::null()) - .stderr(Stdio::inherit()) - .output()?; + let mut command = Command::new(binary); + command.args(args).current_dir(current_dir).stderr(Stdio::inherit()); + let output = match stdin { + None => command.stdin(Stdio::null()).output(), + Some(stdin) => { + command.stdin(Stdio::piped()).stdout(Stdio::piped()); + let mut process = command.spawn()?; + process.stdin.take().unwrap().write_all(stdin)?; + process.wait_with_output() + } + }?; let stdout = String::from_utf8(output.stdout)?; if echo { @@ -133,13 +158,15 @@ fn shelx(cmd: &str) -> Vec { struct Env { pushd_stack: Vec, + pushenv_stack: Vec<(OsString, Option)>, } impl Env { fn with T, T>(f: F) -> T { thread_local! { static ENV: RefCell = RefCell::new(Env { - pushd_stack: vec![env::current_dir().unwrap()] + pushd_stack: vec![env::current_dir().unwrap()], + pushenv_stack: vec![], }); } ENV.with(|it| f(&mut *it.borrow_mut())) @@ -154,6 +181,17 @@ impl Env { self.pushd_stack.pop().unwrap(); env::set_current_dir(self.cwd()).unwrap(); } + fn pushenv(&mut self, var: OsString, value: OsString) { + self.pushenv_stack.push((var.clone(), env::var_os(&var))); + env::set_var(var, value) + } + fn popenv(&mut self) { + let (var, value) = self.pushenv_stack.pop().unwrap(); + match value { + None => env::remove_var(var), + Some(value) => env::set_var(var, value), + } + } fn cwd(&self) -> &Path { self.pushd_stack.last().unwrap() } -- cgit v1.2.3