@@ -10,6 +10,7 @@ import * as url from 'url';
10
10
import { promisify } from 'util' ;
11
11
import { OutputChannel , ProgressLocation , window , WorkspaceFolder } from 'vscode' ;
12
12
import { Logger } from 'vscode-languageclient' ;
13
+ import * as which from 'which' ;
13
14
import * as yazul from 'yauzl' ;
14
15
import { createGunzip } from 'zlib' ;
15
16
@@ -18,7 +19,7 @@ enum LogLevel {
18
19
Error ,
19
20
Warn ,
20
21
Info ,
21
- Debug
22
+ Debug ,
22
23
}
23
24
export class ExtensionLogger implements Logger {
24
25
public readonly name : string ;
@@ -52,7 +53,7 @@ export class ExtensionLogger implements Logger {
52
53
let now = new Date ( ) ;
53
54
// Ugly hack to make js date iso format similar to hls one
54
55
const offset = now . getTimezoneOffset ( ) ;
55
- now = new Date ( now . getTime ( ) - ( offset * 60 * 1000 ) ) ;
56
+ now = new Date ( now . getTime ( ) - offset * 60 * 1000 ) ;
56
57
const timedMsg = `${ new Date ( ) . toISOString ( ) . replace ( 'T' , ' ' ) . replace ( 'Z' , '0000' ) } ${ msg } ` ;
57
58
this . channel . appendLine ( timedMsg ) ;
58
59
if ( this . logFile ) {
@@ -161,87 +162,90 @@ export async function downloadFile(titleMsg: string, src: string, dest: string):
161
162
fs . unlinkSync ( downloadDest ) ;
162
163
}
163
164
164
- const downloadTask = window . withProgress (
165
- {
166
- location : ProgressLocation . Notification ,
167
- title : titleMsg ,
168
- cancellable : false ,
169
- } ,
170
- async ( progress ) => {
171
- const p = new Promise < void > ( ( resolve , reject ) => {
172
- const srcUrl = url . parse ( src ) ;
173
- const opts : https . RequestOptions = {
174
- host : srcUrl . host ,
175
- path : srcUrl . path ,
176
- protocol : srcUrl . protocol ,
177
- port : srcUrl . port ,
178
- headers : userAgentHeader ,
179
- } ;
180
- getWithRedirects ( opts , ( res ) => {
181
- const totalSize = parseInt ( res . headers [ 'content-length' ] || '1' , 10 ) ;
182
- const fileStream = fs . createWriteStream ( downloadDest , { mode : 0o744 } ) ;
183
- let curSize = 0 ;
165
+ const downloadTask = window
166
+ . withProgress (
167
+ {
168
+ location : ProgressLocation . Notification ,
169
+ title : titleMsg ,
170
+ cancellable : false ,
171
+ } ,
172
+ async ( progress ) => {
173
+ const p = new Promise < void > ( ( resolve , reject ) => {
174
+ const srcUrl = url . parse ( src ) ;
175
+ const opts : https . RequestOptions = {
176
+ host : srcUrl . host ,
177
+ path : srcUrl . path ,
178
+ protocol : srcUrl . protocol ,
179
+ port : srcUrl . port ,
180
+ headers : userAgentHeader ,
181
+ } ;
182
+ getWithRedirects ( opts , ( res ) => {
183
+ const totalSize = parseInt ( res . headers [ 'content-length' ] || '1' , 10 ) ;
184
+ const fileStream = fs . createWriteStream ( downloadDest , { mode : 0o744 } ) ;
185
+ let curSize = 0 ;
184
186
185
- // Decompress it if it's a gzip or zip
186
- const needsGunzip =
187
- res . headers [ 'content-type' ] === 'application/gzip' || extname ( srcUrl . path ?? '' ) === '.gz' ;
188
- const needsUnzip = res . headers [ 'content-type' ] === 'application/zip' || extname ( srcUrl . path ?? '' ) === '.zip' ;
189
- if ( needsGunzip ) {
190
- const gunzip = createGunzip ( ) ;
191
- gunzip . on ( 'error' , reject ) ;
192
- res . pipe ( gunzip ) . pipe ( fileStream ) ;
193
- } else if ( needsUnzip ) {
194
- const zipDest = downloadDest + '.zip' ;
195
- const zipFs = fs . createWriteStream ( zipDest ) ;
196
- zipFs . on ( 'error' , reject ) ;
197
- zipFs . on ( 'close' , ( ) => {
198
- yazul . open ( zipDest , ( err , zipfile ) => {
199
- if ( err ) {
200
- throw err ;
201
- }
202
- if ( ! zipfile ) {
203
- throw Error ( "Couldn't decompress zip" ) ;
204
- }
187
+ // Decompress it if it's a gzip or zip
188
+ const needsGunzip =
189
+ res . headers [ 'content-type' ] === 'application/gzip' || extname ( srcUrl . path ?? '' ) === '.gz' ;
190
+ const needsUnzip =
191
+ res . headers [ 'content-type' ] === 'application/zip' || extname ( srcUrl . path ?? '' ) === '.zip' ;
192
+ if ( needsGunzip ) {
193
+ const gunzip = createGunzip ( ) ;
194
+ gunzip . on ( 'error' , reject ) ;
195
+ res . pipe ( gunzip ) . pipe ( fileStream ) ;
196
+ } else if ( needsUnzip ) {
197
+ const zipDest = downloadDest + '.zip' ;
198
+ const zipFs = fs . createWriteStream ( zipDest ) ;
199
+ zipFs . on ( 'error' , reject ) ;
200
+ zipFs . on ( 'close' , ( ) => {
201
+ yazul . open ( zipDest , ( err , zipfile ) => {
202
+ if ( err ) {
203
+ throw err ;
204
+ }
205
+ if ( ! zipfile ) {
206
+ throw Error ( "Couldn't decompress zip" ) ;
207
+ }
205
208
206
- // We only expect *one* file inside each zip
207
- zipfile . on ( 'entry' , ( entry : yazul . Entry ) => {
208
- zipfile . openReadStream ( entry , ( err2 , readStream ) => {
209
- if ( err2 ) {
210
- throw err2 ;
211
- }
212
- readStream ?. pipe ( fileStream ) ;
209
+ // We only expect *one* file inside each zip
210
+ zipfile . on ( 'entry' , ( entry : yazul . Entry ) => {
211
+ zipfile . openReadStream ( entry , ( err2 , readStream ) => {
212
+ if ( err2 ) {
213
+ throw err2 ;
214
+ }
215
+ readStream ?. pipe ( fileStream ) ;
216
+ } ) ;
213
217
} ) ;
214
218
} ) ;
215
219
} ) ;
216
- } ) ;
217
- res . pipe ( zipFs ) ;
218
- } else {
219
- res . pipe ( fileStream ) ;
220
- }
220
+ res . pipe ( zipFs ) ;
221
+ } else {
222
+ res . pipe ( fileStream ) ;
223
+ }
221
224
222
- function toMB ( bytes : number ) {
223
- return bytes / ( 1024 * 1024 ) ;
224
- }
225
+ function toMB ( bytes : number ) {
226
+ return bytes / ( 1024 * 1024 ) ;
227
+ }
225
228
226
- res . on ( 'data' , ( chunk : Buffer ) => {
227
- curSize += chunk . byteLength ;
228
- const msg = `${ toMB ( curSize ) . toFixed ( 1 ) } MB / ${ toMB ( totalSize ) . toFixed ( 1 ) } MB` ;
229
- progress . report ( { message : msg , increment : ( chunk . length / totalSize ) * 100 } ) ;
230
- } ) ;
231
- res . on ( 'error' , reject ) ;
232
- fileStream . on ( 'close' , resolve ) ;
233
- } ) . on ( 'error' , reject ) ;
234
- } ) ;
235
- try {
236
- await p ;
237
- // Finally rename it to the actual dest
238
- fs . renameSync ( downloadDest , dest ) ;
239
- } finally {
240
- // And remember to remove it from the list of current downloads
241
- inFlightDownloads . get ( src ) ?. delete ( dest ) ;
229
+ res . on ( 'data' , ( chunk : Buffer ) => {
230
+ curSize += chunk . byteLength ;
231
+ const msg = `${ toMB ( curSize ) . toFixed ( 1 ) } MB / ${ toMB ( totalSize ) . toFixed ( 1 ) } MB` ;
232
+ progress . report ( { message : msg , increment : ( chunk . length / totalSize ) * 100 } ) ;
233
+ } ) ;
234
+ res . on ( 'error' , reject ) ;
235
+ fileStream . on ( 'close' , resolve ) ;
236
+ } ) . on ( 'error' , reject ) ;
237
+ } ) ;
238
+ try {
239
+ await p ;
240
+ // Finally rename it to the actual dest
241
+ fs . renameSync ( downloadDest , dest ) ;
242
+ } finally {
243
+ // And remember to remove it from the list of current downloads
244
+ inFlightDownloads . get ( src ) ?. delete ( dest ) ;
245
+ }
242
246
}
243
- }
244
- ) . then ( _ => true ) ;
247
+ )
248
+ . then ( ( _ ) => true ) ;
245
249
246
250
try {
247
251
if ( inFlightDownloads . has ( src ) ) {
@@ -250,7 +254,7 @@ export async function downloadFile(titleMsg: string, src: string, dest: string):
250
254
inFlightDownloads . set ( src , new Map ( [ [ dest , downloadTask ] ] ) ) ;
251
255
}
252
256
return await downloadTask ;
253
- } catch ( e : any ) {
257
+ } catch ( e ) {
254
258
await promisify ( fs . unlink ) ( downloadDest ) . catch ( ignoreFileNotExists ) ;
255
259
throw new Error ( `Failed to download ${ src } :\n${ e . message } ` ) ;
256
260
}
@@ -277,17 +281,13 @@ export function executableExists(exe: string): boolean {
277
281
const isWindows = process . platform === 'win32' ;
278
282
const cmd : string = isWindows ? 'where' : 'which' ;
279
283
const out = child_process . spawnSync ( cmd , [ exe ] ) ;
280
- return out . status === 0 || ( isWindows && fileExists ( exe ) ) ;
284
+ return out . status === 0 || ( ! isWindows && ( which . sync ( exe , { nothrow : true } ) ?? '' ) !== '' ) ;
281
285
}
282
286
283
287
export function directoryExists ( path : string ) : boolean {
284
288
return fs . existsSync ( path ) && fs . lstatSync ( path ) . isDirectory ( ) ;
285
289
}
286
290
287
- function fileExists ( path : string ) : boolean {
288
- return fs . existsSync ( path ) && fs . lstatSync ( path ) . isFile ( ) ;
289
- }
290
-
291
291
export function resolvePathPlaceHolders ( path : string , folder ?: WorkspaceFolder ) {
292
292
path = path . replace ( '${HOME}' , os . homedir ) . replace ( '${home}' , os . homedir ) . replace ( / ^ ~ / , os . homedir ) ;
293
293
if ( folder ) {
0 commit comments