diff --git a/src/platform.ts b/src/platform.ts index 73e4bb1804..eb6146fb9a 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -3,12 +3,19 @@ *--------------------------------------------------------*/ import fs = require("fs"); -import os = require("os"); import path = require("path"); import process = require("process"); -import vscode = require("vscode"); import Settings = require("./settings"); +const linuxExePath = "/usr/bin/pwsh"; +const linuxPreviewExePath = "/usr/bin/pwsh-preview"; + +const snapExePath = "/snap/bin/pwsh"; +const snapPreviewExePath = "/snap/bin/pwsh-preview"; + +const macOSExePath = "/usr/local/bin/pwsh"; +const macOSPreviewExePath = "/usr/local/bin/pwsh-preview"; + export enum OperatingSystem { Unknown, Windows, @@ -47,6 +54,13 @@ export function getPlatformDetails(): IPlatformDetails { }; } +/** + * Gets the default instance of PowerShell for the specified platform. + * On Windows, the default version of PowerShell is "Windows PowerShell". + * @param platformDetails Specifies information about the platform - primarily the operating system. + * @param use32Bit On Windows, this boolean determines whether the 32-bit version of Windows PowerShell is returned. + * @returns A string containing the path of the default version of PowerShell. + */ export function getDefaultPowerShellPath( platformDetails: IPlatformDetails, use32Bit: boolean = false): string | null { @@ -68,14 +82,21 @@ export function getDefaultPowerShellPath( : SysnativePowerShellPath; } } else if (platformDetails.operatingSystem === OperatingSystem.MacOS) { - powerShellExePath = "/usr/local/bin/powershell"; - if (fs.existsSync("/usr/local/bin/pwsh")) { - powerShellExePath = "/usr/local/bin/pwsh"; + // Always default to the stable version of PowerShell (if installed) but handle case of only Preview installed + powerShellExePath = macOSExePath; + if (!fs.existsSync(macOSExePath) && fs.existsSync(macOSPreviewExePath)) { + powerShellExePath = macOSPreviewExePath; } } else if (platformDetails.operatingSystem === OperatingSystem.Linux) { - powerShellExePath = "/usr/bin/powershell"; - if (fs.existsSync("/usr/bin/pwsh")) { - powerShellExePath = "/usr/bin/pwsh"; + // Always default to the stable version of PowerShell (if installed) but handle case of only Preview installed + // as well as the Snaps case - https://snapcraft.io/ + powerShellExePath = linuxExePath; + if (!fs.existsSync(linuxExePath) && fs.existsSync(linuxPreviewExePath)) { + powerShellExePath = linuxPreviewExePath; + } else if (fs.existsSync(snapExePath)) { + powerShellExePath = snapExePath; + } else if (fs.existsSync(snapPreviewExePath)) { + powerShellExePath = snapPreviewExePath; } } @@ -108,6 +129,12 @@ export function fixWindowsPowerShellPath(powerShellExePath: string, platformDeta return powerShellExePath; } +/** + * Gets a list of all available PowerShell instance on the specified platform. + * @param platformDetails Specifies information about the platform - primarily the operating system. + * @param sessionSettings Specifies the user/workspace settings. Additional PowerShell exe paths loaded from settings. + * @returns An array of IPowerShellExeDetails objects with the PowerShell name & exe path for each instance found. + */ export function getAvailablePowerShellExes( platformDetails: IPlatformDetails, sessionSettings: Settings.ISettings | undefined): IPowerShellExeDetails[] { @@ -162,13 +189,25 @@ export function getAvailablePowerShellExes( } } else { // Handle Linux and macOS case - paths.push({ - versionName: "PowerShell Core", - exePath: this.getDefaultPowerShellPath(platformDetails), + let exePaths: string[]; + + if (platformDetails.operatingSystem === OperatingSystem.Linux) { + exePaths = [ linuxExePath, snapExePath, linuxPreviewExePath, snapPreviewExePath ]; + } else { + exePaths = [ macOSExePath, macOSPreviewExePath ]; + } + + exePaths.forEach((exePath) => { + if (fs.existsSync(exePath)) { + paths.push({ + versionName: "PowerShell Core" + (/-preview/.test(exePath) ? " Preview" : ""), + exePath, + }); + } }); } - // When unit testing, we don't have session settings to test so skip reading this setting + // When unit testing, we don't have session settings available to test, so skip reading this setting if (sessionSettings) { // Add additional PowerShell paths as configured in settings for (const additionalPowerShellExePath of sessionSettings.powerShellAdditionalExePaths) {