vtcode_config/
env_helpers.rs1pub fn read_env_var(name: &str) -> Option<String> {
9 #[cfg(test)]
10 if let Some(override_value) = test_env_overrides::get(name) {
11 return override_value;
12 }
13 std::env::var(name).ok()
14}
15
16pub fn parse_env_bool(name: &str, default: bool) -> bool {
21 read_env_var(name)
22 .and_then(|value| {
23 let normalized = value.trim().to_ascii_lowercase();
24 match normalized.as_str() {
25 "1" | "true" | "yes" | "on" => Some(true),
26 "0" | "false" | "no" | "off" => Some(false),
27 _ => None,
28 }
29 })
30 .unwrap_or(default)
31}
32
33pub const fn default_true() -> bool {
35 true
36}
37
38pub const fn default_enabled() -> bool {
41 true
42}
43
44#[cfg(test)]
45pub(crate) mod test_env_overrides {
46 use std::collections::HashMap;
47 use std::sync::{Mutex, OnceLock};
48
49 static ENV_OVERRIDES: OnceLock<Mutex<HashMap<String, Option<String>>>> = OnceLock::new();
50
51 fn overrides() -> &'static Mutex<HashMap<String, Option<String>>> {
52 ENV_OVERRIDES.get_or_init(|| Mutex::new(HashMap::new()))
53 }
54
55 pub fn get(name: &str) -> Option<Option<String>> {
56 overrides()
57 .lock()
58 .expect("env overrides lock poisoned")
59 .get(name)
60 .cloned()
61 }
62
63 pub fn set(name: &str, value: Option<&str>) {
64 overrides()
65 .lock()
66 .expect("env overrides lock poisoned")
67 .insert(name.to_string(), value.map(ToOwned::to_owned));
68 }
69
70 pub fn restore(name: &str, previous: Option<Option<String>>) {
71 let mut guard = overrides().lock().expect("env overrides lock poisoned");
72 match previous {
73 Some(value) => {
74 guard.insert(name.to_string(), value);
75 }
76 None => {
77 guard.remove(name);
78 }
79 }
80 }
81}