mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
Preserve Unicode paths in Windows batch aliases (#40570)
## Why Windows batch aliases can fail to invoke Codex when the executable path contains characters that are not representable in the active console code page. ## What changed - Generate same-volume executable paths relative to the batch file using `%~dp0`. - Keep absolute paths as a fallback when the executable and alias are on different volumes. ## Testing Added Windows tests covering a Unicode profile path under code page 437 and an executable on a different volume. GitOrigin-RevId: 10093bbc9f19e4fbe2e22d9397e211a113302f45
This commit is contained in:
Generated
+1
@@ -2280,6 +2280,7 @@ dependencies = [
|
||||
"codex-utils-home-dir",
|
||||
"codex-windows-sandbox",
|
||||
"dotenvy",
|
||||
"pathdiff",
|
||||
"pretty_assertions",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
|
||||
@@ -28,6 +28,7 @@ tokio = { workspace = true, features = ["rt-multi-thread"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
codex-windows-sandbox = { workspace = true }
|
||||
pathdiff = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = { workspace = true }
|
||||
|
||||
@@ -403,7 +403,7 @@ fn prepare_path_entry_for_codex_aliases(
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let batch_script = path.join(format!("{filename}.bat"));
|
||||
let exe = exe.display();
|
||||
let exe = windows_batch_executable_path(&exe, path);
|
||||
std::fs::write(
|
||||
&batch_script,
|
||||
format!(
|
||||
@@ -447,6 +447,14 @@ fn prepare_path_entry_for_codex_aliases(
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn windows_batch_executable_path(executable: &Path, alias_directory: &Path) -> String {
|
||||
pathdiff::diff_paths(executable, alias_directory)
|
||||
.filter(|relative_path| relative_path.is_relative())
|
||||
.map(|relative_path| format!("%~dp0{}", relative_path.display()))
|
||||
.unwrap_or_else(|| executable.display().to_string())
|
||||
}
|
||||
|
||||
fn path_env_with_package_path_dir(
|
||||
install_context: &InstallContext,
|
||||
existing_path: Option<OsString>,
|
||||
@@ -540,6 +548,8 @@ mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::process::CommandExt;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use tempfile::TempDir;
|
||||
@@ -593,6 +603,50 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn windows_batch_alias_preserves_unicode_executable_paths() -> anyhow::Result<()> {
|
||||
let root = TempDir::new()?;
|
||||
let profile = root.path().join("用户");
|
||||
let alias_directory = profile.join(".codex").join("tmp").join("arg0");
|
||||
let executable_directory = profile.join("bin");
|
||||
fs::create_dir_all(&alias_directory)?;
|
||||
fs::create_dir_all(&executable_directory)?;
|
||||
|
||||
let system_root = std::env::var_os("SystemRoot")
|
||||
.ok_or_else(|| anyhow::anyhow!("missing Windows system root"))?;
|
||||
let command_shell = PathBuf::from(system_root).join("System32").join("cmd.exe");
|
||||
let executable = executable_directory.join("cmd.exe");
|
||||
fs::copy(&command_shell, &executable)?;
|
||||
|
||||
let batch_path = alias_directory.join("apply_patch.bat");
|
||||
let executable_path = super::windows_batch_executable_path(&executable, &alias_directory);
|
||||
fs::write(
|
||||
&batch_path,
|
||||
format!("@echo off\r\n\"{executable_path}\" /d /c exit 37\r\n"),
|
||||
)?;
|
||||
|
||||
let output = std::process::Command::new(command_shell)
|
||||
.args(["/d", "/c"])
|
||||
.raw_arg(format!("chcp 437>nul & call \"{}\"", batch_path.display()))
|
||||
.output()?;
|
||||
|
||||
assert_eq!(output.status.code(), Some(37));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn windows_batch_alias_preserves_cross_volume_executable_paths() {
|
||||
assert_eq!(
|
||||
super::windows_batch_executable_path(
|
||||
Path::new(r"D:\Tools\codex.exe"),
|
||||
Path::new(r"C:\Users\person\.codex\tmp\arg0"),
|
||||
),
|
||||
r"D:\Tools\codex.exe",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linux_sandbox_exe_path_prefers_codex_linux_sandbox_alias() -> std::io::Result<()> {
|
||||
let temp_dir = TempDir::new()?;
|
||||
|
||||
Reference in New Issue
Block a user