From 5d4303510cc35571ae99a0a4a7d6ac40ccc03089 Mon Sep 17 00:00:00 2001 From: jif-oai Date: Fri, 6 Mar 2026 14:50:44 +0000 Subject: [PATCH] fix: windows normalization (#13742) --- codex-rs/core/src/config/mod.rs | 5 +++-- codex-rs/core/src/path_utils.rs | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index a5e19b05a..2898faecc 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -47,6 +47,7 @@ use crate::model_provider_info::ModelProviderInfo; use crate::model_provider_info::OLLAMA_CHAT_PROVIDER_REMOVED_ERROR; use crate::model_provider_info::OLLAMA_OSS_PROVIDER_ID; use crate::model_provider_info::built_in_model_providers; +use crate::path_utils::normalize_for_native_workdir; use crate::project_doc::DEFAULT_PROJECT_DOC_FILENAME; use crate::project_doc::LOCAL_PROJECT_DOC_FILENAME; use crate::protocol::AskForApproval; @@ -1760,7 +1761,7 @@ impl Config { let configured_features = Features::from_config(&cfg, &config_profile, feature_overrides); let features = ManagedFeatures::from_configured(configured_features, feature_requirements)?; let windows_sandbox_mode = resolve_windows_sandbox_mode(&cfg, &config_profile); - let resolved_cwd = { + let resolved_cwd = normalize_for_native_workdir({ use std::env; match cwd { @@ -1777,7 +1778,7 @@ impl Config { current } } - }; + }); let additional_writable_roots: Vec = additional_writable_roots .into_iter() .map(|path| AbsolutePathBuf::resolve_path_against_base(path, &resolved_cwd)) diff --git a/codex-rs/core/src/path_utils.rs b/codex-rs/core/src/path_utils.rs index 4885679e5..af7d62077 100644 --- a/codex-rs/core/src/path_utils.rs +++ b/codex-rs/core/src/path_utils.rs @@ -12,6 +12,10 @@ pub fn normalize_for_path_comparison(path: impl AsRef) -> std::io::Result< Ok(normalize_for_wsl(canonical)) } +pub fn normalize_for_native_workdir(path: impl AsRef) -> PathBuf { + normalize_for_native_workdir_with_flag(path.as_ref().to_path_buf(), cfg!(windows)) +} + pub struct SymlinkWritePaths { pub read_path: Option, pub write_path: PathBuf, @@ -116,6 +120,14 @@ fn normalize_for_wsl(path: PathBuf) -> PathBuf { normalize_for_wsl_with_flag(path, env::is_wsl()) } +fn normalize_for_native_workdir_with_flag(path: PathBuf, is_windows: bool) -> PathBuf { + if is_windows { + dunce::simplified(&path).to_path_buf() + } else { + path + } +} + fn normalize_for_wsl_with_flag(path: PathBuf, is_wsl: bool) -> PathBuf { if !is_wsl { return path; @@ -240,4 +252,30 @@ mod tests { assert_eq!(normalized, path); } } + + mod native_workdir { + use super::super::normalize_for_native_workdir_with_flag; + use pretty_assertions::assert_eq; + use std::path::PathBuf; + + #[cfg(target_os = "windows")] + #[test] + fn windows_verbatim_paths_are_simplified() { + let path = PathBuf::from(r"\\?\D:\c\x\worktrees\2508\swift-base"); + let normalized = normalize_for_native_workdir_with_flag(path, true); + + assert_eq!( + normalized, + PathBuf::from(r"D:\c\x\worktrees\2508\swift-base") + ); + } + + #[test] + fn non_windows_paths_are_unchanged() { + let path = PathBuf::from(r"\\?\D:\c\x\worktrees\2508\swift-base"); + let normalized = normalize_for_native_workdir_with_flag(path.clone(), false); + + assert_eq!(normalized, path); + } + } }