use std::collections::HashMap;
use std::path::Path;
use vcs_runner::Cmd;
pub fn mise_env(dir: &Path) -> HashMap<String, String> {
let Ok(output) = Cmd::new("mise").args(["env", "--json"]).in_dir(dir).run() else {
return HashMap::new();
};
parse(&output.stdout_lossy()).unwrap_or_else(|e| {
eprintln!("Warning: could not read `mise env --json` output ({e}); the session starts without mise's env");
HashMap::new()
})
}
fn parse(output: &str) -> Result<HashMap<String, String>, serde_json::Error> {
let map: HashMap<String, serde_json::Value> = serde_json::from_str(output)?;
Ok(map.into_iter().filter_map(|(k, v)| v.as_str().map(|s| (k, s.to_string()))).collect())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn keeps_values_verbatim() {
let output = r#"{
"PATH": "/usr/local/bin:/usr/bin",
"W_DQUOTE": "say \"hi\"",
"W_EMPTY": "",
"W_NL": "line1\nline2",
"W_SQUOTE": "it's",
"W_TRAILQ": "x'"
}"#;
let vars = parse(output).unwrap();
assert_eq!(vars.get("PATH").unwrap(), "/usr/local/bin:/usr/bin");
assert_eq!(vars.get("W_DQUOTE").unwrap(), "say \"hi\"");
assert_eq!(vars.get("W_EMPTY").unwrap(), "");
assert_eq!(vars.get("W_NL").unwrap(), "line1\nline2");
assert_eq!(vars.get("W_SQUOTE").unwrap(), "it's");
assert_eq!(vars.get("W_TRAILQ").unwrap(), "x'");
assert_eq!(vars.len(), 6);
}
#[test]
fn skips_non_strings() {
let vars = parse(r#"{"A": "a", "B": 1, "C": null}"#).unwrap();
assert_eq!(vars, HashMap::from([("A".to_string(), "a".to_string())]));
}
#[test]
fn output_that_is_not_a_json_object_is_an_error() {
assert!(parse("export A=a\n").is_err(), "shell-form output is not JSON");
assert!(parse("").is_err());
assert!(parse("[1]").is_err());
}
}