forked from facebook/buck2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenv_vars.rs
More file actions
84 lines (72 loc) · 2.51 KB
/
Copy pathenv_vars.rs
File metadata and controls
84 lines (72 loc) · 2.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is dual-licensed under either the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree or the Apache
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
* of this source tree. You may select, at your option, one of the
* above-listed licenses.
*/
use std::env::VarError;
use once_cell::sync::Lazy;
use regex::Regex;
/// Replace occurrences of `$FOO` in a string with the value of the env var `$FOO`.
/// Returns an error if any referenced variable is not set.
pub fn substitute_env_vars(s: &str) -> buck2_error::Result<String> {
substitute_env_vars_impl(s, |v| std::env::var(v))
}
pub fn substitute_env_vars_impl(
s: &str,
getter: impl Fn(&str) -> Result<String, VarError>,
) -> buck2_error::Result<String> {
static ENV_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new("\\$[a-zA-Z_][a-zA-Z_0-9]*").unwrap());
let mut out = String::with_capacity(s.len());
let mut last_idx = 0;
for mat in ENV_REGEX.find_iter(s) {
out.push_str(&s[last_idx..mat.start()]);
let var = &mat.as_str()[1..];
let val = getter(var).map_err(|e| {
buck2_error::buck2_error!(
buck2_error::ErrorTag::Environment,
"Error substituting `{}`: {}",
mat.as_str(),
e
)
})?;
out.push_str(&val);
last_idx = mat.end();
}
if last_idx < s.len() {
out.push_str(&s[last_idx..s.len()]);
}
Ok(out)
}
#[cfg(test)]
mod tests {
use std::env::VarError;
use super::*;
#[test]
fn test_substitute_env_vars() {
let getter = |s: &str| match s {
"FOO" => Ok("foo_value".to_owned()),
"BAR" => Ok("bar_value".to_owned()),
"BAZ" => Err(VarError::NotPresent),
_ => panic!("Unexpected"),
};
assert_eq!(
substitute_env_vars_impl("$FOO", getter).unwrap(),
"foo_value"
);
assert_eq!(
substitute_env_vars_impl("$FOO$BAR", getter).unwrap(),
"foo_valuebar_value"
);
assert_eq!(
substitute_env_vars_impl("some$FOO.bar", getter).unwrap(),
"somefoo_value.bar"
);
assert_eq!(substitute_env_vars_impl("foo", getter).unwrap(), "foo");
assert_eq!(substitute_env_vars_impl("FOO", getter).unwrap(), "FOO");
assert!(substitute_env_vars_impl("$FOO$BAZ", getter).is_err());
}
}