Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion crates/askpass/src/askpass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ 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 {}",
Expand Down
10 changes: 4 additions & 6 deletions crates/gpui/src/platform/windows/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,12 +390,10 @@ impl Platform for WindowsPlatform {
clippy::disallowed_methods,
reason = "We are restarting ourselves, using std command thus is fine"
)]
// 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();
let restart_process = util::command::new_std_command("powershell.exe")
.arg("-command")
.arg(script)
.spawn();

match restart_process {
Ok(_) => self.quit(),
Expand Down
80 changes: 32 additions & 48 deletions crates/util/src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, fmt, path::Path, sync::LazyLock};

use crate::command::new_std_command;

/// Shell configuration to open the terminal with.
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Hash)]
#[serde(rename_all = "snake_case")]
Expand Down Expand Up @@ -110,12 +108,16 @@ pub fn get_windows_system_shell() -> String {
use std::path::PathBuf;

fn find_pwsh_in_programfiles(find_alternate: bool, find_preview: bool) -> Option<PathBuf> {
#[cfg(target_pointer_width = "64")]
let env_var = if find_alternate {
if cfg!(target_pointer_width = "64") {
"ProgramFiles(x86)"
} else {
"ProgramW6432"
}
"ProgramFiles(x86)"
} else {
"ProgramFiles"
};

#[cfg(target_pointer_width = "32")]
let env_var = if find_alternate {
"ProgramW6432"
} else {
"ProgramFiles"
};
Expand Down Expand Up @@ -163,19 +165,23 @@ pub fn get_windows_system_shell() -> String {
} else {
"Microsoft.PowerShell_"
};
msix_app_dir.read_dir().ok()?.find_map(|entry| {
let entry = entry.ok()?;
if !matches!(entry.file_type(), Ok(ft) if ft.is_dir()) {
return None;
}
msix_app_dir
.read_dir()
.ok()?
.filter_map(|entry| {
let entry = entry.ok()?;
if !matches!(entry.file_type(), Ok(ft) if ft.is_dir()) {
return None;
}

if !entry.file_name().to_string_lossy().starts_with(prefix) {
return None;
}
if !entry.file_name().to_string_lossy().starts_with(prefix) {
return None;
}

let exe_path = entry.path().join("pwsh.exe");
exe_path.exists().then_some(exe_path)
})
let exe_path = entry.path().join("pwsh.exe");
exe_path.exists().then_some(exe_path)
})
.next()
}

fn find_pwsh_in_scoop() -> Option<PathBuf> {
Expand All @@ -184,37 +190,15 @@ pub fn get_windows_system_shell() -> String {
pwsh_exe.exists().then_some(pwsh_exe)
}

// check whether the found powershell is executable for us
static SYSTEM_SHELL: LazyLock<String> = LazyLock::new(|| {
let can_execute_pwsh = |p: &PathBuf| {
#[allow(clippy::disallowed_methods)]
let status = new_std_command(p).arg("-NoProfile").arg("-Help").status();
let success = status.as_ref().is_ok_and(|status| status.success());
if !success {
log::warn!(
"Powershell found at `{}` is not executable: {status:?}",
p.display()
);
}
success
};

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()
.filter_map(|f| f())
.find(|p| can_execute_pwsh(&p))
.map(|p| p.to_string_lossy().trim().to_owned())
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())
.inspect(|shell| log::info!("Found powershell in: {}", shell))
.unwrap_or_else(|| {
log::warn!("Powershell not found, falling back to `cmd`");
Expand Down