Skip to content

Commit

Permalink
Remove the MSI install logic (it's buggy)
Browse files Browse the repository at this point in the history
And instead just open the release in the browser for the user.
  • Loading branch information
andyleejordan committed May 10, 2023
1 parent 436fd90 commit b9f70e8
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 86 deletions.
90 changes: 6 additions & 84 deletions src/features/UpdatePowerShell.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { spawn } from "child_process";
import * as fs from "fs"; // TODO: Remove, but it's for a stream.
import fetch from "node-fetch";
import * as os from "os";
import * as path from "path";
import { SemVer } from "semver";
import * as stream from "stream";
import * as util from "util";
import vscode = require("vscode");

import { ILogger } from "../logging";
import { IPowerShellVersionDetails, SessionManager } from "../session";
import { IPowerShellVersionDetails } from "../session";
import { changeSetting, Settings } from "../settings";
import { isWindows } from "../utils";

const streamPipeline = util.promisify(stream.pipeline);

interface IUpdateMessageItem extends vscode.MessageItem {
id: number;
Expand All @@ -29,7 +20,6 @@ export class UpdatePowerShell {
private static LTSBuildInfoURL = "https://aka.ms/pwsh-buildinfo-lts";
private static StableBuildInfoURL = "https://aka.ms/pwsh-buildinfo-stable";
private static PreviewBuildInfoURL = "https://aka.ms/pwsh-buildinfo-preview";
private static GitHubAPIReleaseURL = "https://api.github.com/repos/PowerShell/PowerShell/releases/tags/";
private static GitHubWebReleaseURL = "https://github.com/PowerShell/PowerShell/releases/tag/";
private static promptOptions: IUpdateMessageItem[] = [
{
Expand All @@ -46,10 +36,8 @@ export class UpdatePowerShell {
},
];
private localVersion: SemVer;
private architecture: string;

constructor(
private sessionManager: SessionManager,
private sessionSettings: Settings,
private logger: ILogger,
versionDetails: IPowerShellVersionDetails) {
Expand All @@ -58,7 +46,6 @@ export class UpdatePowerShell {
// to SemVer. The version handler in PSES handles Windows PowerShell and
// just returns the first three fields like '5.1.22621'.
this.localVersion = new SemVer(versionDetails.commit);
this.architecture = versionDetails.architecture.toLowerCase();
}

private shouldCheckForUpdate(): boolean {
Expand Down Expand Up @@ -173,74 +160,13 @@ export class UpdatePowerShell {
await vscode.env.openExternal(url);
}

private async updateWindows(tag: string): Promise<void> {
let msiMatcher: string;
if (this.architecture === "x64") {
msiMatcher = "win-x64.msi";
} else if (this.architecture === "x86") {
msiMatcher = "win-x86.msi";
} else {
// We shouldn't get here, but do something sane anyway.
return this.openReleaseInBrowser(tag);
}

let response = await fetch(UpdatePowerShell.GitHubAPIReleaseURL + tag);
if (!response.ok) {
throw new Error("Failed to fetch GitHub release info!");
}
const release = await response.json();

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const asset = release.assets.filter((a: any) => a.name.indexOf(msiMatcher) >= 0)[0];
const msiDownloadPath = path.join(os.tmpdir(), asset.name);

response = await fetch(asset.browser_download_url);
if (!response.ok) {
throw new Error("Failed to fetch MSI!");
}

const progressOptions = {
title: "Downloading PowerShell Installer...",
location: vscode.ProgressLocation.Notification,
cancellable: false,
};
// Streams the body of the request to a file.
await vscode.window.withProgress(progressOptions,
async () => { await streamPipeline(response.body, fs.createWriteStream(msiDownloadPath)); });

// Stop the session because Windows likes to hold on to files.
this.logger.writeDiagnostic("MSI downloaded, stopping session and closing terminals!");
await this.sessionManager.stop();

// Close all terminals with the name "pwsh" in the current VS Code session.
// This will encourage folks to not close the instance of VS Code that spawned
// the MSI process.
for (const terminal of vscode.window.terminals) {
if (terminal.name === "pwsh") {
terminal.dispose();
}
}

// Invoke the MSI via cmd.
this.logger.writeDiagnostic(`Running '${msiDownloadPath}' to update PowerShell...`);
const msi = spawn("msiexec", ["/i", msiDownloadPath]);

msi.on("close", () => {
// Now that the MSI is finished, restart the session.
this.logger.writeDiagnostic("MSI installation finished, restarting session.");
void this.sessionManager.start();
fs.unlinkSync(msiDownloadPath);
});
}

private async installUpdate(tag: string): Promise<void> {
const releaseVersion = new SemVer(tag);
const result = await vscode.window.showInformationMessage(
`You have an old version of PowerShell (${this.localVersion.version}). The current latest release is ${releaseVersion.version}.
Would you like to update the version? ${isWindows
? "This will close ALL pwsh terminals running in this VS Code session!"
: "We can't update you automatically, but we can open the latest release in your browser!"
}`, ...UpdatePowerShell.promptOptions);
`You have an old version of PowerShell (${this.localVersion.version}).
The current latest release is ${releaseVersion.version}.
Would you like to open the GitHub release in your browser?`,
...UpdatePowerShell.promptOptions);

// If the user cancels the notification.
if (!result) {
Expand All @@ -253,11 +179,7 @@ export class UpdatePowerShell {
switch (result.id) {
// Yes
case 0:
if (isWindows && (this.architecture === "x64" || this.architecture === "x86")) {
await this.updateWindows(tag);
} else {
await this.openReleaseInBrowser(tag);
}
await this.openReleaseInBrowser(tag);
break;
// Not Now
case 1:
Expand Down
4 changes: 2 additions & 2 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ export class SessionManager implements Middleware {
"commit": version, // Actually used by UpdatePowerShell
"architecture": process.arch // Best guess based off Code's architecture
};
const updater = new UpdatePowerShell(this, this.sessionSettings, this.logger, versionDetails);
const updater = new UpdatePowerShell(this.sessionSettings, this.logger, versionDetails);
void updater.checkForUpdate();
}
return;
Expand Down Expand Up @@ -735,7 +735,7 @@ Type 'help' to get help.
// We haven't "started" until we're done getting the version information.
this.started = true;

const updater = new UpdatePowerShell(this, this.sessionSettings, this.logger, this.versionDetails);
const updater = new UpdatePowerShell(this.sessionSettings, this.logger, this.versionDetails);
// NOTE: We specifically don't want to wait for this.
void updater.checkForUpdate();
}
Expand Down

0 comments on commit b9f70e8

Please sign in to comment.