From 7cc054ec04b3b0bc36189181834126f3a56bffc1 Mon Sep 17 00:00:00 2001 From: Alexander Vostres Date: Wed, 1 Apr 2026 22:52:01 +0300 Subject: [PATCH 1/2] Fix for 'forge zsh setup' command when running Windows native forge.exe in MSYS2 zsh environment forge.exe had CRLF line endings in .zsh files, and also running scripts via 'zsh -c' was failing for some weird reasons. --- .gitattributes | 1 + crates/forge_main/src/zsh/plugin.rs | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..524f2a407e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.zsh eol=lf diff --git a/crates/forge_main/src/zsh/plugin.rs b/crates/forge_main/src/zsh/plugin.rs index 363f2afeaf..19009d5206 100644 --- a/crates/forge_main/src/zsh/plugin.rs +++ b/crates/forge_main/src/zsh/plugin.rs @@ -11,6 +11,11 @@ use include_dir::{Dir, include_dir}; use crate::cli::Cli; +/// Normalizes CRLF to LF for scripts embedded via `include_str!` on Windows +fn normalize_line_endings(s: &str) -> String { + s.replace("\r\n", "\n") +} + /// Embeds shell plugin files for zsh integration static ZSH_PLUGIN_LIB: Dir<'static> = include_dir!("$CARGO_MANIFEST_DIR/../../shell-plugin/lib"); @@ -51,7 +56,7 @@ pub fn generate_zsh_plugin() -> Result { /// Generates the ZSH theme for Forge pub fn generate_zsh_theme() -> Result { - let mut content = include_str!("../../../../shell-plugin/forge.theme.zsh").to_string(); + let mut content = normalize_line_endings(include_str!("../../../../shell-plugin/forge.theme.zsh")); // Set environment variable to indicate theme is loaded (with timestamp) content.push_str("\n_FORGE_THEME_LOADED=$(date +%s)\n"); @@ -71,10 +76,15 @@ pub fn generate_zsh_theme() -> Result { /// Returns error if the script cannot be executed, if output streaming fails, /// or if the script exits with a non-zero status code fn execute_zsh_script_with_streaming(script_content: &str, script_name: &str) -> Result<()> { + // Write script to a temp file to avoid Windows command-line escaping issues + let temp_dir = std::env::temp_dir(); + let script_path = temp_dir.join(format!("forge_{}.zsh", script_name)); + fs::write(&script_path, script_content) + .context(format!("Failed to write temp script for {}", script_name))?; + // Execute the script in a zsh subprocess with piped output let mut child = std::process::Command::new("zsh") - .arg("-c") - .arg(script_content) + .arg(script_path.to_str().unwrap()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -114,6 +124,9 @@ fn execute_zsh_script_with_streaming(script_content: &str, script_name: &str) -> .wait() .context(format!("Failed to wait for zsh {} script", script_name))?; + // Clean up temp script file + let _ = fs::remove_file(&script_path); + if !status.success() { let exit_code = status .code() @@ -135,8 +148,8 @@ fn execute_zsh_script_with_streaming(script_content: &str, script_name: &str) -> /// /// Returns error if the doctor script cannot be executed pub fn run_zsh_doctor() -> Result<()> { - let script_content = include_str!("../../../../shell-plugin/doctor.zsh"); - execute_zsh_script_with_streaming(script_content, "doctor") + let script_content = normalize_line_endings(include_str!("../../../../shell-plugin/doctor.zsh")); + execute_zsh_script_with_streaming(&script_content, "doctor") } /// Shows ZSH keyboard shortcuts with streaming output @@ -145,8 +158,8 @@ pub fn run_zsh_doctor() -> Result<()> { /// /// Returns error if the keyboard script cannot be executed pub fn run_zsh_keyboard() -> Result<()> { - let script_content = include_str!("../../../../shell-plugin/keyboard.zsh"); - execute_zsh_script_with_streaming(script_content, "keyboard") + let script_content = normalize_line_endings(include_str!("../../../../shell-plugin/keyboard.zsh")); + execute_zsh_script_with_streaming(&script_content, "keyboard") } /// Represents the state of markers in a file From a21fb45f1a85137cf23464400465a892a4b13d06 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 03:49:43 +0000 Subject: [PATCH 2/2] [autofix.ci] apply automated fixes --- crates/forge_main/src/zsh/plugin.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/forge_main/src/zsh/plugin.rs b/crates/forge_main/src/zsh/plugin.rs index 19009d5206..30ce9e7d90 100644 --- a/crates/forge_main/src/zsh/plugin.rs +++ b/crates/forge_main/src/zsh/plugin.rs @@ -56,7 +56,8 @@ pub fn generate_zsh_plugin() -> Result { /// Generates the ZSH theme for Forge pub fn generate_zsh_theme() -> Result { - let mut content = normalize_line_endings(include_str!("../../../../shell-plugin/forge.theme.zsh")); + let mut content = + normalize_line_endings(include_str!("../../../../shell-plugin/forge.theme.zsh")); // Set environment variable to indicate theme is loaded (with timestamp) content.push_str("\n_FORGE_THEME_LOADED=$(date +%s)\n"); @@ -148,7 +149,8 @@ fn execute_zsh_script_with_streaming(script_content: &str, script_name: &str) -> /// /// Returns error if the doctor script cannot be executed pub fn run_zsh_doctor() -> Result<()> { - let script_content = normalize_line_endings(include_str!("../../../../shell-plugin/doctor.zsh")); + let script_content = + normalize_line_endings(include_str!("../../../../shell-plugin/doctor.zsh")); execute_zsh_script_with_streaming(&script_content, "doctor") } @@ -158,7 +160,8 @@ pub fn run_zsh_doctor() -> Result<()> { /// /// Returns error if the keyboard script cannot be executed pub fn run_zsh_keyboard() -> Result<()> { - let script_content = normalize_line_endings(include_str!("../../../../shell-plugin/keyboard.zsh")); + let script_content = + normalize_line_endings(include_str!("../../../../shell-plugin/keyboard.zsh")); execute_zsh_script_with_streaming(&script_content, "keyboard") }