docs(plan): make tilde expansion injectable rather than env-mutating

The tilde test set HOME via unsafe std::env::set_var. That is sound under
nextest (process per test) but hazardous under cargo test, and the runner
is not something a unit test should depend on. expand_tilde now takes the
home directory as a parameter; parse_wait_for reads $HOME once and passes
it down.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGntTHCW3sEPy1VBRopNNp
This commit is contained in:
2026-08-07 15:28:49 +02:00
co-authored by Claude Opus 5
parent 73e17d51f3
commit c000a00f05
@@ -77,18 +77,24 @@ fn parses_a_path_condition_with_defaults() {
} }
#[test] #[test]
fn expands_a_leading_tilde_in_a_path_condition() { fn expands_a_leading_tilde_against_the_given_home() {
unsafe { std::env::set_var("HOME", "/home/someone") }; let home = PathBuf::from("/home/someone");
let text = "command \"/bin/x\"\nport 1\nwait-for { path \"~/.orbstack/run/docker.sock\" }";
let cfg = parse_server_config("foo", text, p()).unwrap();
assert_eq!( assert_eq!(
cfg.wait_for.unwrap().condition, expand_tilde("~/.orbstack/run/docker.sock", Some(&home)),
WaitCondition::Path(PathBuf::from("/home/someone/.orbstack/run/docker.sock")) PathBuf::from("/home/someone/.orbstack/run/docker.sock")
); );
} }
#[test]
fn leaves_non_tilde_paths_and_unknown_home_alone() {
let home = PathBuf::from("/home/someone");
assert_eq!(expand_tilde("/var/run/d.sock", Some(&home)), PathBuf::from("/var/run/d.sock"));
assert_eq!(expand_tilde("~/a", None), PathBuf::from("~/a"));
assert_eq!(expand_tilde("~weird/a", Some(&home)), PathBuf::from("~weird/a"));
}
#[test] #[test]
fn parses_a_tcp_condition_with_overrides() { fn parses_a_tcp_condition_with_overrides() {
let text = "command \"/bin/x\"\nport 1\nwait-for { tcp \"127.0.0.1:5432\"\ntimeout \"30s\"\ninterval \"250ms\" }"; let text = "command \"/bin/x\"\nport 1\nwait-for { tcp \"127.0.0.1:5432\"\ntimeout \"30s\"\ninterval \"250ms\" }";
@@ -246,13 +252,13 @@ and the field `wait_for,` in the returned `ServerConfig`.
Then add these functions: Then add these functions:
```rust ```rust
fn expand_tilde(raw: &str) -> PathBuf { fn expand_tilde(raw: &str, home: Option<&Path>) -> PathBuf {
let Some(rest) = raw.strip_prefix("~/") else { let Some(rest) = raw.strip_prefix("~/") else {
return PathBuf::from(raw); return PathBuf::from(raw);
}; };
match std::env::var_os("HOME") { match home {
Some(home) => PathBuf::from(home).join(rest), Some(home) => home.join(rest),
None => PathBuf::from(raw), None => PathBuf::from(raw),
} }
} }
@@ -272,6 +278,8 @@ fn parse_wait_for(doc: &KdlDocument, path: &Path) -> Result<Option<WaitForConfig
return Err(invalid("expected a block with exactly one condition".into())); return Err(invalid("expected a block with exactly one condition".into()));
}; };
let home = std::env::var_os("HOME").map(PathBuf::from);
let mut conditions: Vec<WaitCondition> = Vec::new(); let mut conditions: Vec<WaitCondition> = Vec::new();
let mut command: Option<PathBuf> = None; let mut command: Option<PathBuf> = None;
let mut args: Vec<String> = Vec::new(); let mut args: Vec<String> = Vec::new();
@@ -283,7 +291,7 @@ fn parse_wait_for(doc: &KdlDocument, path: &Path) -> Result<Option<WaitForConfig
"path" => { "path" => {
let raw = string_arg(child, "wait-for", path)?; let raw = string_arg(child, "wait-for", path)?;
conditions.push(WaitCondition::Path(expand_tilde(&raw))); conditions.push(WaitCondition::Path(expand_tilde(&raw, home.as_deref())));
} }
"tcp" => { "tcp" => {
let addr = string_arg(child, "wait-for", path)?; let addr = string_arg(child, "wait-for", path)?;