fix(tui): split effective_home_dir into a leaf so skill_cli can resolve it
tests/skill_cli.rs pulls network_policy.rs and skills/install.rs into the test binary via #[path] includes, so `crate::` there is the test binary's root rather than the lib. #4757 replaced dirs::home_dir() with crate::config::effective_home_dir() in both files, leaving two E0433s and a broken test build on every platform: error[E0433]: cannot find `config` in `crate` --> crates/tui/tests/../src/network_policy.rs:324:27 --> crates/tui/tests/../src/skills/install.rs:64:12 The obvious fix — include config/paths.rs behind a `mod config` shim — does not work. Integration test binaries compile with cfg(test) set, so paths.rs brings its `crate::test_support` call with it, and test_support brings `crate::config_persistence` behind that. Shimming each layer would put three stand-ins for production code in the test, including a fake env mutex, which is a worse test than none. effective_home_dir was already a leaf over std/dirs; it just shared a file with the cfg(test)-gated env_config_path. Move it to config/home.rs, which has no crate:: references at all, and re-export from paths.rs so config::effective_home_dir and every `use paths::{...}` caller resolve unchanged. The test binary includes that one file and gets the real implementation rather than a divergent shim. skill_cli is the only affected test binary; the other #[path]-including tests pull files with no crate::config references. Signed-off-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5797,6 +5797,7 @@ fn root_deepseek_model_is_foreign_to_direct_provider(provider: ApiProvider, mode
|
||||
// `pub(crate)` entry points are re-exported so external `crate::config::`
|
||||
// callers resolve unchanged; the remaining helpers are imported privately for
|
||||
// the workspace-trust/config-load logic that stays in this file (#3311).
|
||||
mod home;
|
||||
mod paths;
|
||||
use paths::{
|
||||
canonicalize_or_keep, codewhale_home_dir, default_config_path, default_managed_config_path,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
//! Home-directory resolution, kept as a dependency-free leaf.
|
||||
//!
|
||||
//! This is one function that could live in `paths.rs` — and did, until #4757
|
||||
//! made it the crate-wide replacement for `dirs::home_dir()`. Two of the new
|
||||
//! call sites (`network_policy.rs`, `skills/install.rs`) are pulled into the
|
||||
//! `skill_cli` integration test via `#[path]` includes, where `crate::` means
|
||||
//! the test binary's root rather than the lib. Anything they reach for has to
|
||||
//! be includable there too.
|
||||
//!
|
||||
//! `paths.rs` is not: its `env_config_path` calls `crate::test_support` under
|
||||
//! `#[cfg(test)]`, and integration test binaries compile *with* `cfg(test)`
|
||||
//! set, so including it drags in `test_support` — and then
|
||||
//! `config_persistence` behind that. Splitting this function out keeps the
|
||||
//! includable surface to `std` + `dirs` with no `crate::` references at all,
|
||||
//! so the test binary picks up production behavior verbatim instead of a
|
||||
//! divergent shim.
|
||||
//!
|
||||
//! `paths.rs` re-exports this so `config::effective_home_dir` and every
|
||||
//! existing `use paths::{...}` caller resolve unchanged.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Resolve the user's home directory, preferring the environment over the
|
||||
/// platform lookup so tests can fake it consistently across OSes (#4757).
|
||||
///
|
||||
/// `HOME` and `USERPROFILE` are checked first (empty values are treated as
|
||||
/// unset, since an empty home is never a usable path), then the Windows
|
||||
/// `HOMEDRIVE`/`HOMEPATH` pair, and only then `dirs::home_dir()`. Keeping the
|
||||
/// OS lookup last is what makes a faked environment win in tests while
|
||||
/// production still falls back to the real thing.
|
||||
pub(crate) fn effective_home_dir() -> Option<PathBuf> {
|
||||
if let Some(path) = std::env::var_os("HOME") {
|
||||
let path = PathBuf::from(path);
|
||||
if !path.as_os_str().is_empty() {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(path) = std::env::var_os("USERPROFILE") {
|
||||
let path = PathBuf::from(path);
|
||||
if !path.as_os_str().is_empty() {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let (Some(drive), Some(homepath)) =
|
||||
(std::env::var_os("HOMEDRIVE"), std::env::var_os("HOMEPATH"))
|
||||
{
|
||||
let mut path = PathBuf::from(drive);
|
||||
path.push(homepath);
|
||||
if !path.as_os_str().is_empty() {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirs::home_dir()
|
||||
}
|
||||
@@ -13,6 +13,11 @@
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Re-exported so `config::effective_home_dir` and every `use paths::{...}`
|
||||
/// caller resolve unchanged. It lives in `home.rs` because this module is not
|
||||
/// includable from an integration test binary — see that file's header.
|
||||
pub(crate) use super::home::effective_home_dir;
|
||||
|
||||
pub(crate) fn default_config_path() -> Option<PathBuf> {
|
||||
env_config_path().or_else(home_config_path)
|
||||
}
|
||||
@@ -24,37 +29,6 @@ pub(crate) fn codewhale_home_dir() -> Option<PathBuf> {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn effective_home_dir() -> Option<PathBuf> {
|
||||
if let Some(path) = std::env::var_os("HOME") {
|
||||
let path = PathBuf::from(path);
|
||||
if !path.as_os_str().is_empty() {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(path) = std::env::var_os("USERPROFILE") {
|
||||
let path = PathBuf::from(path);
|
||||
if !path.as_os_str().is_empty() {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let (Some(drive), Some(homepath)) =
|
||||
(std::env::var_os("HOMEDRIVE"), std::env::var_os("HOMEPATH"))
|
||||
{
|
||||
let mut path = PathBuf::from(drive);
|
||||
path.push(homepath);
|
||||
if !path.as_os_str().is_empty() {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirs::home_dir()
|
||||
}
|
||||
|
||||
pub(crate) fn home_config_path() -> Option<PathBuf> {
|
||||
if let Some(home) = codewhale_home_dir() {
|
||||
return Some(home.join("config.toml"));
|
||||
|
||||
@@ -25,6 +25,15 @@ use tiny_http::{Method, Response, Server};
|
||||
#[path = "../src/network_policy.rs"]
|
||||
mod network_policy;
|
||||
|
||||
// Both `network_policy` and `install` resolve the home directory through
|
||||
// `crate::config::effective_home_dir()` (#4757). `config/home.rs` is a leaf
|
||||
// over `std`/`dirs` with no `crate::` references, so including it here gives
|
||||
// this binary the real implementation; naming it `config` matches how those
|
||||
// two files address it in the lib.
|
||||
#[path = "../src/config/home.rs"]
|
||||
#[allow(dead_code)]
|
||||
mod config;
|
||||
|
||||
#[path = "../src/skills/package_digest.rs"]
|
||||
#[allow(dead_code)]
|
||||
mod package_digest;
|
||||
|
||||
Reference in New Issue
Block a user