diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-10-17 01:44:12 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-10-17 01:44:12 +0100 |
commit | 59483c217662fc5d89ef9da1cb93760e14a48418 (patch) | |
tree | cf93fa6a4f3d18e8be27acf56ee85927fd6f66c7 /xtask/src/not_bash.rs | |
parent | f0412da4a2c06e50030d13e37002d0440fc7cded (diff) | |
parent | 49a90d4c31148a6533d9ee9a288f42b454b2f421 (diff) |
Merge #6260
6260: xshell r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'xtask/src/not_bash.rs')
-rw-r--r-- | xtask/src/not_bash.rs | 169 |
1 files changed, 0 insertions, 169 deletions
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs deleted file mode 100644 index 038898993..000000000 --- a/xtask/src/not_bash.rs +++ /dev/null | |||
@@ -1,169 +0,0 @@ | |||
1 | //! A bad shell -- small cross platform module for writing glue code | ||
2 | |||
3 | use std::{ | ||
4 | cell::RefCell, | ||
5 | env, | ||
6 | ffi::OsString, | ||
7 | io::{self, Write}, | ||
8 | path::{Path, PathBuf}, | ||
9 | process::{Command, Stdio}, | ||
10 | }; | ||
11 | |||
12 | use anyhow::{bail, Context, Result}; | ||
13 | |||
14 | pub use fs_err as fs2; | ||
15 | |||
16 | #[macro_export] | ||
17 | macro_rules! run { | ||
18 | ($($expr:expr),*) => { | ||
19 | run!($($expr),*; echo = true) | ||
20 | }; | ||
21 | ($($expr:expr),* ; echo = $echo:expr) => { | ||
22 | $crate::not_bash::run_process(format!($($expr),*), $echo, None) | ||
23 | }; | ||
24 | ($($expr:expr),* ; <$stdin:expr) => { | ||
25 | $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin)) | ||
26 | }; | ||
27 | } | ||
28 | pub use crate::run; | ||
29 | |||
30 | pub struct Pushd { | ||
31 | _p: (), | ||
32 | } | ||
33 | |||
34 | pub fn pushd(path: impl Into<PathBuf>) -> Pushd { | ||
35 | Env::with(|env| env.pushd(path.into())); | ||
36 | Pushd { _p: () } | ||
37 | } | ||
38 | |||
39 | impl Drop for Pushd { | ||
40 | fn drop(&mut self) { | ||
41 | Env::with(|env| env.popd()) | ||
42 | } | ||
43 | } | ||
44 | |||
45 | pub struct Pushenv { | ||
46 | _p: (), | ||
47 | } | ||
48 | |||
49 | pub fn pushenv(var: &str, value: &str) -> Pushenv { | ||
50 | Env::with(|env| env.pushenv(var.into(), value.into())); | ||
51 | Pushenv { _p: () } | ||
52 | } | ||
53 | |||
54 | impl Drop for Pushenv { | ||
55 | fn drop(&mut self) { | ||
56 | Env::with(|env| env.popenv()) | ||
57 | } | ||
58 | } | ||
59 | |||
60 | pub fn rm_rf(path: impl AsRef<Path>) -> io::Result<()> { | ||
61 | let path = path.as_ref(); | ||
62 | if !path.exists() { | ||
63 | return Ok(()); | ||
64 | } | ||
65 | if path.is_file() { | ||
66 | fs2::remove_file(path) | ||
67 | } else { | ||
68 | fs2::remove_dir_all(path) | ||
69 | } | ||
70 | } | ||
71 | |||
72 | #[doc(hidden)] | ||
73 | pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> { | ||
74 | run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd)) | ||
75 | } | ||
76 | |||
77 | pub fn date_iso() -> Result<String> { | ||
78 | run!("date --iso --utc") | ||
79 | } | ||
80 | |||
81 | fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<String> { | ||
82 | let mut args = shelx(cmd); | ||
83 | let binary = args.remove(0); | ||
84 | let current_dir = Env::with(|it| it.cwd().to_path_buf()); | ||
85 | |||
86 | if echo { | ||
87 | println!("> {}", cmd) | ||
88 | } | ||
89 | |||
90 | let mut command = Command::new(binary); | ||
91 | command.args(args).current_dir(current_dir).stderr(Stdio::inherit()); | ||
92 | let output = match stdin { | ||
93 | None => command.stdin(Stdio::null()).output(), | ||
94 | Some(stdin) => { | ||
95 | command.stdin(Stdio::piped()).stdout(Stdio::piped()); | ||
96 | let mut process = command.spawn()?; | ||
97 | process.stdin.take().unwrap().write_all(stdin)?; | ||
98 | process.wait_with_output() | ||
99 | } | ||
100 | }?; | ||
101 | let stdout = String::from_utf8(output.stdout)?; | ||
102 | |||
103 | if echo { | ||
104 | print!("{}", stdout) | ||
105 | } | ||
106 | |||
107 | if !output.status.success() { | ||
108 | bail!("{}", output.status) | ||
109 | } | ||
110 | |||
111 | Ok(stdout.trim().to_string()) | ||
112 | } | ||
113 | |||
114 | // FIXME: some real shell lexing here | ||
115 | fn shelx(cmd: &str) -> Vec<String> { | ||
116 | let mut res = Vec::new(); | ||
117 | for (string_piece, in_quotes) in cmd.split('\'').zip([false, true].iter().copied().cycle()) { | ||
118 | if in_quotes { | ||
119 | res.push(string_piece.to_string()) | ||
120 | } else { | ||
121 | if !string_piece.is_empty() { | ||
122 | res.extend(string_piece.split_ascii_whitespace().map(|it| it.to_string())) | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | res | ||
127 | } | ||
128 | |||
129 | struct Env { | ||
130 | pushd_stack: Vec<PathBuf>, | ||
131 | pushenv_stack: Vec<(OsString, Option<OsString>)>, | ||
132 | } | ||
133 | |||
134 | impl Env { | ||
135 | fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { | ||
136 | thread_local! { | ||
137 | static ENV: RefCell<Env> = RefCell::new(Env { | ||
138 | pushd_stack: vec![env::current_dir().unwrap()], | ||
139 | pushenv_stack: vec![], | ||
140 | }); | ||
141 | } | ||
142 | ENV.with(|it| f(&mut *it.borrow_mut())) | ||
143 | } | ||
144 | |||
145 | fn pushd(&mut self, dir: PathBuf) { | ||
146 | let dir = self.cwd().join(dir); | ||
147 | self.pushd_stack.push(dir); | ||
148 | env::set_current_dir(self.cwd()) | ||
149 | .unwrap_or_else(|err| panic!("Failed to set cwd to {}: {}", self.cwd().display(), err)); | ||
150 | } | ||
151 | fn popd(&mut self) { | ||
152 | self.pushd_stack.pop().unwrap(); | ||
153 | env::set_current_dir(self.cwd()).unwrap(); | ||
154 | } | ||
155 | fn pushenv(&mut self, var: OsString, value: OsString) { | ||
156 | self.pushenv_stack.push((var.clone(), env::var_os(&var))); | ||
157 | env::set_var(var, value) | ||
158 | } | ||
159 | fn popenv(&mut self) { | ||
160 | let (var, value) = self.pushenv_stack.pop().unwrap(); | ||
161 | match value { | ||
162 | None => env::remove_var(var), | ||
163 | Some(value) => env::set_var(var, value), | ||
164 | } | ||
165 | } | ||
166 | fn cwd(&self) -> &Path { | ||
167 | self.pushd_stack.last().unwrap() | ||
168 | } | ||
169 | } | ||