2
2
* Copyright (C) Microsoft Corporation. All rights reserved.
3
3
*--------------------------------------------------------*/
4
4
5
+ import { spawn } from "child_process" ;
6
+ import * as fs from "fs" ;
5
7
import fetch , { RequestInit } from "node-fetch" ;
8
+ import * as os from "os" ;
9
+ import * as path from "path" ;
6
10
import * as semver from "semver" ;
7
- import { MessageItem , window } from "vscode" ;
11
+ import * as stream from "stream" ;
12
+ import * as util from "util" ;
13
+ import { MessageItem , ProgressLocation , window } from "vscode" ;
8
14
import { LanguageClient } from "vscode-languageclient" ;
15
+ import { SessionManager } from "../session" ;
9
16
import * as Settings from "../settings" ;
17
+ import { isMacOS , isWindows } from "../utils" ;
10
18
import { EvaluateRequestType } from "./Console" ;
11
19
20
+ const streamPipeline = util . promisify ( stream . pipeline ) ;
21
+
12
22
const PowerShellGitHubReleasesUrl =
13
23
"https://api.github.com/repos/PowerShell/PowerShell/releases/latest" ;
14
24
const PowerShellGitHubPrereleasesUrl =
@@ -67,6 +77,7 @@ interface IUpdateMessageItem extends MessageItem {
67
77
}
68
78
69
79
export async function InvokePowerShellUpdateCheck (
80
+ sessionManager : SessionManager ,
70
81
languageServerClient : LanguageClient ,
71
82
localVersion : semver . SemVer ,
72
83
arch : string ,
@@ -103,7 +114,6 @@ export async function InvokePowerShellUpdateCheck(
103
114
return ;
104
115
}
105
116
106
- const isMacOS : boolean = process . platform === "darwin" ;
107
117
const result = await window . showInformationMessage (
108
118
`${ commonText } Would you like to update the version? ${
109
119
isMacOS ? "(Homebrew is required on macOS)" : ""
@@ -116,39 +126,50 @@ export async function InvokePowerShellUpdateCheck(
116
126
switch ( result . id ) {
117
127
// Yes choice.
118
128
case 0 :
119
- let script : string ;
120
- if ( process . platform === "win32" ) {
129
+ if ( isWindows ) {
121
130
const msiMatcher = arch === "x86" ?
122
131
"win-x86.msi" : "win-x64.msi" ;
123
132
124
- const assetUrl = release . assets . filter ( ( asset : any ) =>
125
- asset . name . indexOf ( msiMatcher ) >= 0 ) [ 0 ] . browser_download_url ;
126
-
127
- // Grab MSI and run it.
128
- // tslint:disable-next-line: max-line-length
129
- script = `
130
- $randomFileName = [System.IO.Path]::GetRandomFileName()
131
- $tmpMsiPath = Microsoft.PowerShell.Management\\Join-Path ([System.IO.Path]::GetTempPath()) "$randomFileName.msi"
132
- Microsoft.PowerShell.Utility\\Invoke-RestMethod -Uri ${ assetUrl } -OutFile $tmpMsiPath
133
- try
134
- {
135
- Microsoft.PowerShell.Management\\Start-Process -Wait -Path $tmpMsiPath
136
- }
137
- finally
138
- {
139
- Microsoft.PowerShell.Management\\Remove-Item $tmpMsiPath
140
- }` ;
133
+ const asset = release . assets . filter ( ( a : any ) => a . name . indexOf ( msiMatcher ) >= 0 ) [ 0 ] ;
134
+ const msiDownloadPath = path . join ( os . tmpdir ( ) , asset . name ) ;
141
135
142
- } else if ( isMacOS ) {
143
- script = "brew cask upgrade powershell" ;
144
- if ( release . isPreview ) {
145
- script = "brew cask upgrade powershell-preview" ;
136
+ const res = await fetch ( asset . browser_download_url ) ;
137
+ if ( ! res . ok ) {
138
+ throw new Error ( "unable to fetch MSI" ) ;
146
139
}
140
+
141
+ await window . withProgress ( {
142
+ title : "Downloading PowerShell Installer..." ,
143
+ location : ProgressLocation . Notification ,
144
+ cancellable : false ,
145
+ } ,
146
+ async ( ) => {
147
+ // Streams the body of the request to a file.
148
+ await streamPipeline ( res . body , fs . createWriteStream ( msiDownloadPath ) ) ;
149
+ } ) ;
150
+
151
+ // Stop the Integrated Console session because Windows likes to hold on to files.
152
+ sessionManager . stop ( ) ;
153
+
154
+ // Invoke the MSI via cmd.
155
+ const msi = spawn ( "msiexec" , [ "/i" , msiDownloadPath ] ) ;
156
+
157
+ msi . on ( "close" , ( code ) => {
158
+ // Now that the MSI is finished, start the Integrated Console session.
159
+ sessionManager . start ( ) ;
160
+ fs . unlinkSync ( msiDownloadPath ) ;
161
+ } ) ;
162
+
163
+ } else if ( isMacOS ) {
164
+ const script = release . isPreview
165
+ ? "brew cask upgrade powershell-preview"
166
+ : "brew cask upgrade powershell" ;
167
+
168
+ await languageServerClient . sendRequest ( EvaluateRequestType , {
169
+ expression : script ,
170
+ } ) ;
147
171
}
148
172
149
- await languageServerClient . sendRequest ( EvaluateRequestType , {
150
- expression : script ,
151
- } ) ;
152
173
break ;
153
174
154
175
// Never choice.
0 commit comments