Show More
@@ -150,6 +150,7 b' impl ConfigLayer {' | |||||
150 | let line = Some(index + 1); |
|
150 | let line = Some(index + 1); | |
151 | if let Some(m) = INCLUDE_RE.captures(&bytes) { |
|
151 | if let Some(m) = INCLUDE_RE.captures(&bytes) { | |
152 | let filename_bytes = &m[1]; |
|
152 | let filename_bytes = &m[1]; | |
|
153 | let filename_bytes = crate::utils::expand_vars(filename_bytes); | |||
153 | // `Path::parent` only fails for the root directory, |
|
154 | // `Path::parent` only fails for the root directory, | |
154 | // which `src` can’t be since we’ve managed to open it as a |
|
155 | // which `src` can’t be since we’ve managed to open it as a | |
155 | // file. |
|
156 | // file. |
@@ -241,6 +241,59 b' pub fn current_exe() -> Result<std::path' | |||||
241 | }) |
|
241 | }) | |
242 | } |
|
242 | } | |
243 |
|
243 | |||
|
244 | /// Expand `$FOO` and `${FOO}` environment variables in the given byte string | |||
|
245 | pub fn expand_vars(s: &[u8]) -> std::borrow::Cow<[u8]> { | |||
|
246 | lazy_static::lazy_static! { | |||
|
247 | /// https://github.com/python/cpython/blob/3.9/Lib/posixpath.py#L301 | |||
|
248 | /// The `x` makes whitespace ignored. | |||
|
249 | /// `-u` disables the Unicode flag, which makes `\w` like Python with the ASCII flag. | |||
|
250 | static ref VAR_RE: regex::bytes::Regex = | |||
|
251 | regex::bytes::Regex::new(r"(?x-u) | |||
|
252 | \$ | |||
|
253 | (?: | |||
|
254 | (\w+) | |||
|
255 | | | |||
|
256 | \{ | |||
|
257 | ([^}]*) | |||
|
258 | \} | |||
|
259 | ) | |||
|
260 | ").unwrap(); | |||
|
261 | } | |||
|
262 | VAR_RE.replace_all(s, |captures: ®ex::bytes::Captures| { | |||
|
263 | let var_name = files::get_os_str_from_bytes( | |||
|
264 | captures | |||
|
265 | .get(1) | |||
|
266 | .or_else(|| captures.get(2)) | |||
|
267 | .expect("either side of `|` must participate in match") | |||
|
268 | .as_bytes(), | |||
|
269 | ); | |||
|
270 | std::env::var_os(var_name) | |||
|
271 | .map(files::get_bytes_from_os_str) | |||
|
272 | .unwrap_or_else(|| { | |||
|
273 | // Referencing an environment variable that does not exist. | |||
|
274 | // Leave the $FOO reference as-is. | |||
|
275 | captures[0].to_owned() | |||
|
276 | }) | |||
|
277 | }) | |||
|
278 | } | |||
|
279 | ||||
|
280 | #[test] | |||
|
281 | fn test_expand_vars() { | |||
|
282 | // Modifying process-global state in a test isn’t great, | |||
|
283 | // but hopefully this won’t collide with anything. | |||
|
284 | std::env::set_var("TEST_EXPAND_VAR", "1"); | |||
|
285 | assert_eq!( | |||
|
286 | expand_vars(b"before/$TEST_EXPAND_VAR/after"), | |||
|
287 | &b"before/1/after"[..] | |||
|
288 | ); | |||
|
289 | assert_eq!( | |||
|
290 | expand_vars(b"before${TEST_EXPAND_VAR}${TEST_EXPAND_VAR}${TEST_EXPAND_VAR}after"), | |||
|
291 | &b"before111after"[..] | |||
|
292 | ); | |||
|
293 | let s = b"before $SOME_LONG_NAME_THAT_WE_ASSUME_IS_NOT_AN_ACTUAL_ENV_VAR after"; | |||
|
294 | assert_eq!(expand_vars(s), &s[..]); | |||
|
295 | } | |||
|
296 | ||||
244 | pub(crate) enum MergeResult<V> { |
|
297 | pub(crate) enum MergeResult<V> { | |
245 | UseLeftValue, |
|
298 | UseLeftValue, | |
246 | UseRightValue, |
|
299 | UseRightValue, |
@@ -23,7 +23,7 b' use std::iter::FusedIterator;' | |||||
23 | use std::ops::Deref; |
|
23 | use std::ops::Deref; | |
24 | use std::path::{Path, PathBuf}; |
|
24 | use std::path::{Path, PathBuf}; | |
25 |
|
25 | |||
26 |
pub fn get_ |
|
26 | pub fn get_os_str_from_bytes(bytes: &[u8]) -> &OsStr { | |
27 | let os_str; |
|
27 | let os_str; | |
28 | #[cfg(unix)] |
|
28 | #[cfg(unix)] | |
29 | { |
|
29 | { | |
@@ -33,8 +33,11 b' pub fn get_path_from_bytes(bytes: &[u8])' | |||||
33 | // TODO Handle other platforms |
|
33 | // TODO Handle other platforms | |
34 | // TODO: convert from WTF8 to Windows MBCS (ANSI encoding). |
|
34 | // TODO: convert from WTF8 to Windows MBCS (ANSI encoding). | |
35 | // Perhaps, the return type would have to be Result<PathBuf>. |
|
35 | // Perhaps, the return type would have to be Result<PathBuf>. | |
|
36 | os_str | |||
|
37 | } | |||
36 |
|
38 | |||
37 | Path::new(os_str) |
|
39 | pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { | |
|
40 | Path::new(get_os_str_from_bytes(bytes)) | |||
38 | } |
|
41 | } | |
39 |
|
42 | |||
40 | // TODO: need to convert from WTF8 to MBCS bytes on Windows. |
|
43 | // TODO: need to convert from WTF8 to MBCS bytes on Windows. |
General Comments 0
You need to be logged in to leave comments.
Login now