From 269f3b22fdd1e5fc72c4c03b3b964fe0aa7dbaa7 Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Fri, 6 Nov 2026 00:08:35 +0800 Subject: [PATCH] fix(terminal): disable pwsh update banners by default on Windows (#1588) --- crates/ide-terminal/src/lib.rs | 63 ++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/crates/ide-terminal/src/lib.rs b/crates/ide-terminal/src/lib.rs index ebe53e311..c53426a54 100644 --- a/crates/ide-terminal/src/lib.rs +++ b/crates/ide-terminal/src/lib.rs @@ -120,6 +120,7 @@ impl TerminalManager { for (k, v) in env { cmd.env(k, v); } + apply_powershell_env(&shell, &mut cmd); let child = pair .slave @@ -633,6 +634,18 @@ fn terminal_env(user: &BTreeMap) -> BTreeMap { env } +/// Older pwsh versions can crash while formatting a localized update banner +/// (PowerShell/PowerShell#28131). Keep explicit preferences in the final environment. +fn apply_powershell_env(shell: &str, cmd: &mut CommandBuilder) { + let name = shell.rsplit(['/', '\\']).next().unwrap_or(shell); + if cfg!(windows) + && (name.eq_ignore_ascii_case("pwsh") || name.eq_ignore_ascii_case("pwsh.exe")) + && cmd.get_env("POWERSHELL_UPDATECHECK").is_none_or(|v| v.is_empty()) + { + cmd.env("POWERSHELL_UPDATECHECK", "Off"); + } +} + /// Git Bash's MSYSTEM profile on Windows, when nobody chose one. A bare /// `bash.exe` would run with the `MSYS` default, whose PATH leaves `git` and /// the mingw64 tools out unless `\cmd` happens to be inherited — the Git @@ -938,6 +951,56 @@ mod tests { mod shell_start_on_every_platform { use super::*; + #[test] + fn powershell_update_notifications_default_to_off_on_windows() { + for shell in ["pwsh", "pwsh.exe", "PWSH.EXE", "C:\\Program Files\\PowerShell\\7\\PwSh.ExE", "C:/pwsh/pwsh.exe"] + { + for value in [None, Some("")] { + let mut cmd = CommandBuilder::new(shell); + cmd.env_clear(); + if let Some(value) = value { + cmd.env("POWERSHELL_UPDATECHECK", value); + } + apply_powershell_env(shell, &mut cmd); + let want = if cfg!(windows) { Some("Off") } else { value }; + assert_eq!(cmd.get_env("POWERSHELL_UPDATECHECK"), want.map(std::ffi::OsStr::new), "{shell}"); + } + } + } + + #[test] + fn powershell_update_notification_preferences_are_preserved() { + for value in ["Default", "LTS", "Off"] { + let mut cmd = CommandBuilder::new("pwsh.exe"); + cmd.env_clear(); + cmd.env("POWERSHELL_UPDATECHECK", value); + apply_powershell_env("pwsh.exe", &mut cmd); + assert_eq!(cmd.get_env("POWERSHELL_UPDATECHECK"), Some(std::ffi::OsStr::new(value))); + } + } + + #[cfg(windows)] + #[test] + fn powershell_update_notification_preferences_ignore_key_case() { + let mut cmd = CommandBuilder::new("pwsh.exe"); + cmd.env_clear(); + cmd.env("POWERSHELL_UPDATECHECK", "Off"); + cmd.env("powershell_updatecheck", "Default"); + apply_powershell_env("pwsh.exe", &mut cmd); + assert_eq!(cmd.get_env("POWERSHELL_UPDATECHECK"), Some(std::ffi::OsStr::new("Default"))); + assert_eq!(cmd.iter_full_env_as_str().count(), 1); + } + + #[test] + fn other_shells_keep_their_update_notification_environment() { + for shell in ["powershell.exe", "cmd.exe", "wsl.exe", "bash.exe", "C:\\pwsh.exe\\other.exe", "other-pwsh.exe"] { + let mut cmd = CommandBuilder::new(shell); + cmd.env_clear(); + apply_powershell_env(shell, &mut cmd); + assert_eq!(cmd.get_env("POWERSHELL_UPDATECHECK"), None, "{shell}"); + } + } + #[test] fn posix_shells_start_as_login_shells_everywhere() { let (shell, args) = resolve_shell(Some("C:\\Program Files\\Git\\bin\\bash.exe"), &[]);