shell: Correctly identifiy `powershell` shells on windows (#43526)

Lukas Wirth created

Release Notes:

- Fixed zed only finding pwsh but not powershell on windows

Change summary

crates/askpass/src/askpass.rs                |  1 
crates/gpui/src/platform/windows/platform.rs | 11 +++++----
crates/util/src/shell.rs                     | 24 ++++++++++++++-------
3 files changed, 23 insertions(+), 13 deletions(-)

Detailed changes

crates/askpass/src/askpass.rs 🔗

@@ -250,6 +250,7 @@ impl PasswordProxy {
             .await
             .with_context(|| format!("creating askpass script at {askpass_script_path:?}"))?;
         make_file_executable(&askpass_script_path).await?;
+        // todo(shell): There might be no powershell on the system
         #[cfg(target_os = "windows")]
         let askpass_helper = format!(
             "powershell.exe -ExecutionPolicy Bypass -File {}",

crates/gpui/src/platform/windows/platform.rs 🔗

@@ -389,11 +389,12 @@ impl Platform for WindowsPlatform {
         #[allow(
             clippy::disallowed_methods,
             reason = "We are restarting ourselves, using std command thus is fine"
-        )]
-        let restart_process = util::command::new_std_command("powershell.exe")
-            .arg("-command")
-            .arg(script)
-            .spawn();
+        )] // todo(shell): There might be no powershell on the system
+        let restart_process =
+            util::command::new_std_command(util::shell::get_windows_system_shell())
+                .arg("-command")
+                .arg(script)
+                .spawn();
 
         match restart_process {
             Ok(_) => self.quit(),

crates/util/src/shell.rs 🔗

@@ -204,14 +204,22 @@ pub fn get_windows_system_shell() -> String {
     }
 
     static SYSTEM_SHELL: LazyLock<String> = LazyLock::new(|| {
-        find_pwsh_in_programfiles(false, false)
-            .or_else(|| find_pwsh_in_programfiles(true, false))
-            .or_else(|| find_pwsh_in_msix(false))
-            .or_else(|| find_pwsh_in_programfiles(false, true))
-            .or_else(|| find_pwsh_in_msix(true))
-            .or_else(|| find_pwsh_in_programfiles(true, true))
-            .or_else(find_pwsh_in_scoop)
-            .map(|p| p.to_string_lossy().into_owned())
+        let locations = [
+            || find_pwsh_in_programfiles(false, false),
+            || find_pwsh_in_programfiles(true, false),
+            || find_pwsh_in_msix(false),
+            || find_pwsh_in_programfiles(false, true),
+            || find_pwsh_in_msix(true),
+            || find_pwsh_in_programfiles(true, true),
+            || find_pwsh_in_scoop(),
+            || which::which_global("pwsh.exe").ok(),
+            || which::which_global("powershell.exe").ok(),
+        ];
+
+        locations
+            .into_iter()
+            .find_map(|f| f())
+            .map(|p| p.to_string_lossy().trim().to_owned())
             .inspect(|shell| log::info!("Found powershell in: {}", shell))
             .unwrap_or_else(|| {
                 log::warn!("Powershell not found, falling back to `cmd`");