Skip to content

Inject an Env seam into home directory resolution #486

Description

@leynos

Context

home_from_env in src/stdlib/path/path_utils.rs:155-170 reads up to five environment variables ambiently, across two #[cfg] branches:

#[cfg(windows)]
fn home_from_env() -> Option<String> {
    env::var("HOME")
        .or_else(|_| env::var("USERPROFILE"))
        .ok()
        .or_else(|| match (env::var("HOMEDRIVE").ok(), env::var("HOMEPATH").ok()) {
            (Some(drive), Some(path)) if !path.is_empty() => Some(format!("{drive}{path}")),
            _ => env::var("HOMESHARE").ok(),
        })
}

This is the worst offender in the codebase for ambient environment access: a five-variable precedence ladder with an empty-string edge case, none of which can be exercised without mutating the real environment. The Windows branch is additionally unreachable from the CI host. Under the AGENTS.md testing mandate it currently has no legitimate test route at all.

Required work

  • Take an injected environment reader (a closure Fn(&str) -> Option<String>) in home_from_env and its callers, supplying the process-backed reader at the stdlib::path boundary.
  • Make the #[cfg(windows)] ladder testable independently of the host by extracting the precedence logic into a cfg-free helper that takes the injected environment, leaving only the platform selection behind #[cfg].
  • Add rstest cases covering: HOME set; HOME unset with USERPROFILE set; the HOMEDRIVE/HOMEPATH pair; the empty-HOMEPATH edge case falling through to HOMESHARE; and nothing set.

Acceptance criteria

  • No env::var call remains in src/stdlib/path/path_utils.rs.
  • The Windows precedence ladder is covered by tests that run on a Unix CI host.
  • make check-fmt, make lint, and make test pass.

Amended 2026-08-05: the injection requirement originally named mockable::Env/mockable::DefaultEnv. The repository's established seam for this boundary is a closure reader (as in stdlib::path, output_mode, output_prefs, and theme), and adding a trait-object dependency for one call site is disproportionate; the requirement now states the closure seam that PR #499 implements. The substance — no ambient env::var in path_utils.rs, both ladders testable from a Unix host — is unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmediumRoadmap items to schedule within the current quarter. Clear scope, normal review cycles.refactorBehaviour-preserving restructuring that improves code health.testingTest coverage, test infrastructure, and verification tooling work.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions