diff options
Diffstat (limited to 'xtask/src/not_bash.rs')
-rw-r--r-- | xtask/src/not_bash.rs | 60 |
1 files changed, 49 insertions, 11 deletions
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 @@ | |||
3 | use std::{ | 3 | use std::{ |
4 | cell::RefCell, | 4 | cell::RefCell, |
5 | env, | 5 | env, |
6 | ffi::OsString, | ||
7 | io::Write, | ||
6 | path::{Path, PathBuf}, | 8 | path::{Path, PathBuf}, |
7 | process::{Command, Stdio}, | 9 | process::{Command, Stdio}, |
8 | }; | 10 | }; |
@@ -57,7 +59,10 @@ macro_rules! _run { | |||
57 | run!($($expr),*; echo = true) | 59 | run!($($expr),*; echo = true) |
58 | }; | 60 | }; |
59 | ($($expr:expr),* ; echo = $echo:expr) => { | 61 | ($($expr:expr),* ; echo = $echo:expr) => { |
60 | $crate::not_bash::run_process(format!($($expr),*), $echo) | 62 | $crate::not_bash::run_process(format!($($expr),*), $echo, None) |
63 | }; | ||
64 | ($($expr:expr),* ; <$stdin:expr) => { | ||
65 | $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin)) | ||
61 | }; | 66 | }; |
62 | } | 67 | } |
63 | pub(crate) use _run as run; | 68 | pub(crate) use _run as run; |
@@ -77,6 +82,21 @@ impl Drop for Pushd { | |||
77 | } | 82 | } |
78 | } | 83 | } |
79 | 84 | ||
85 | pub struct Pushenv { | ||
86 | _p: (), | ||
87 | } | ||
88 | |||
89 | pub fn pushenv(var: &str, value: &str) -> Pushenv { | ||
90 | Env::with(|env| env.pushenv(var.into(), value.into())); | ||
91 | Pushenv { _p: () } | ||
92 | } | ||
93 | |||
94 | impl Drop for Pushenv { | ||
95 | fn drop(&mut self) { | ||
96 | Env::with(|env| env.popenv()) | ||
97 | } | ||
98 | } | ||
99 | |||
80 | pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> { | 100 | pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> { |
81 | let path = path.as_ref(); | 101 | let path = path.as_ref(); |
82 | if !path.exists() { | 102 | if !path.exists() { |
@@ -90,15 +110,15 @@ pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> { | |||
90 | } | 110 | } |
91 | 111 | ||
92 | #[doc(hidden)] | 112 | #[doc(hidden)] |
93 | pub fn run_process(cmd: String, echo: bool) -> Result<String> { | 113 | pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> { |
94 | run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd)) | 114 | run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd)) |
95 | } | 115 | } |
96 | 116 | ||
97 | pub fn date_iso() -> Result<String> { | 117 | pub fn date_iso() -> Result<String> { |
98 | run!("date --iso --utc") | 118 | run!("date --iso --utc") |
99 | } | 119 | } |
100 | 120 | ||
101 | fn run_process_inner(cmd: &str, echo: bool) -> Result<String> { | 121 | fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<String> { |
102 | let mut args = shelx(cmd); | 122 | let mut args = shelx(cmd); |
103 | let binary = args.remove(0); | 123 | let binary = args.remove(0); |
104 | let current_dir = Env::with(|it| it.cwd().to_path_buf()); | 124 | let current_dir = Env::with(|it| it.cwd().to_path_buf()); |
@@ -107,12 +127,17 @@ fn run_process_inner(cmd: &str, echo: bool) -> Result<String> { | |||
107 | println!("> {}", cmd) | 127 | println!("> {}", cmd) |
108 | } | 128 | } |
109 | 129 | ||
110 | let output = Command::new(binary) | 130 | let mut command = Command::new(binary); |
111 | .args(args) | 131 | command.args(args).current_dir(current_dir).stderr(Stdio::inherit()); |
112 | .current_dir(current_dir) | 132 | let output = match stdin { |
113 | .stdin(Stdio::null()) | 133 | None => command.stdin(Stdio::null()).output(), |
114 | .stderr(Stdio::inherit()) | 134 | Some(stdin) => { |
115 | .output()?; | 135 | command.stdin(Stdio::piped()).stdout(Stdio::piped()); |
136 | let mut process = command.spawn()?; | ||
137 | process.stdin.take().unwrap().write_all(stdin)?; | ||
138 | process.wait_with_output() | ||
139 | } | ||
140 | }?; | ||
116 | let stdout = String::from_utf8(output.stdout)?; | 141 | let stdout = String::from_utf8(output.stdout)?; |
117 | 142 | ||
118 | if echo { | 143 | if echo { |
@@ -133,13 +158,15 @@ fn shelx(cmd: &str) -> Vec<String> { | |||
133 | 158 | ||
134 | struct Env { | 159 | struct Env { |
135 | pushd_stack: Vec<PathBuf>, | 160 | pushd_stack: Vec<PathBuf>, |
161 | pushenv_stack: Vec<(OsString, Option<OsString>)>, | ||
136 | } | 162 | } |
137 | 163 | ||
138 | impl Env { | 164 | impl Env { |
139 | fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { | 165 | fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { |
140 | thread_local! { | 166 | thread_local! { |
141 | static ENV: RefCell<Env> = RefCell::new(Env { | 167 | static ENV: RefCell<Env> = RefCell::new(Env { |
142 | pushd_stack: vec![env::current_dir().unwrap()] | 168 | pushd_stack: vec![env::current_dir().unwrap()], |
169 | pushenv_stack: vec![], | ||
143 | }); | 170 | }); |
144 | } | 171 | } |
145 | ENV.with(|it| f(&mut *it.borrow_mut())) | 172 | ENV.with(|it| f(&mut *it.borrow_mut())) |
@@ -154,6 +181,17 @@ impl Env { | |||
154 | self.pushd_stack.pop().unwrap(); | 181 | self.pushd_stack.pop().unwrap(); |
155 | env::set_current_dir(self.cwd()).unwrap(); | 182 | env::set_current_dir(self.cwd()).unwrap(); |
156 | } | 183 | } |
184 | fn pushenv(&mut self, var: OsString, value: OsString) { | ||
185 | self.pushenv_stack.push((var.clone(), env::var_os(&var))); | ||
186 | env::set_var(var, value) | ||
187 | } | ||
188 | fn popenv(&mut self) { | ||
189 | let (var, value) = self.pushenv_stack.pop().unwrap(); | ||
190 | match value { | ||
191 | None => env::remove_var(var), | ||
192 | Some(value) => env::set_var(var, value), | ||
193 | } | ||
194 | } | ||
157 | fn cwd(&self) -> &Path { | 195 | fn cwd(&self) -> &Path { |
158 | self.pushd_stack.last().unwrap() | 196 | self.pushd_stack.last().unwrap() |
159 | } | 197 | } |