33
44'use strict' ;
55
6+ import { inject , injectable , named } from 'inversify' ;
67import * as path from 'path' ;
78import { ProgressLocation , window } from 'vscode' ;
89import { IApplicationShell } from '../common/application/types' ;
910import { STANDARD_OUTPUT_CHANNEL } from '../common/constants' ;
1011import { IFileSystem } from '../common/platform/types' ;
11- import { IExtensionContext , IOutputChannel } from '../common/types' ;
12+ import { IOutputChannel } from '../common/types' ;
1213import { createDeferred } from '../common/utils/async' ;
1314import { LanguageService } from '../common/utils/localize' ;
1415import { StopWatch } from '../common/utils/stopWatch' ;
15- import { IServiceContainer } from '../ioc/types' ;
1616import { sendTelemetryEvent } from '../telemetry' ;
1717import {
1818 PYTHON_LANGUAGE_SERVER_DOWNLOADED ,
1919 PYTHON_LANGUAGE_SERVER_ERROR ,
2020 PYTHON_LANGUAGE_SERVER_EXTRACTED
2121} from '../telemetry/constants' ;
22- import {
23- IHttpClient , ILanguageServerDownloader , ILanguageServerFolderService ,
24- ILanguageServerPlatformData
25- } from './types' ;
22+ import { IHttpClient , ILanguageServerDownloader , ILanguageServerFolderService , IPlatformData } from './types' ;
2623
2724const downloadFileExtension = '.nupkg' ;
2825
26+ @injectable ( )
2927export class LanguageServerDownloader implements ILanguageServerDownloader {
30- private readonly output : IOutputChannel ;
31- private readonly fs : IFileSystem ;
32- private readonly appShell : IApplicationShell ;
3328 constructor (
34- private readonly platformData : ILanguageServerPlatformData ,
35- private readonly engineFolder : string ,
36- private readonly serviceContainer : IServiceContainer
29+ @inject ( IPlatformData ) private readonly platformData : IPlatformData ,
30+ @inject ( IOutputChannel ) @named ( STANDARD_OUTPUT_CHANNEL ) private readonly output : IOutputChannel ,
31+ @inject ( IHttpClient ) private readonly httpClient : IHttpClient ,
32+ @inject ( ILanguageServerFolderService ) private readonly lsFolderService : ILanguageServerFolderService ,
33+ @inject ( IApplicationShell ) private readonly appShell : IApplicationShell ,
34+ @inject ( IFileSystem ) private readonly fs : IFileSystem
3735 ) {
38- this . output = this . serviceContainer . get < IOutputChannel > ( IOutputChannel , STANDARD_OUTPUT_CHANNEL ) ;
39- this . fs = this . serviceContainer . get < IFileSystem > ( IFileSystem ) ;
40- this . appShell = this . serviceContainer . get < IApplicationShell > ( IApplicationShell ) ;
41-
4236 }
4337
4438 public async getDownloadInfo ( ) {
45- const lsFolderService = this . serviceContainer . get < ILanguageServerFolderService > ( ILanguageServerFolderService ) ;
46- return lsFolderService . getLatestLanguageServerVersion ( ) . then ( item => item ! ) ;
39+ return this . lsFolderService . getLatestLanguageServerVersion ( ) . then ( item => item ! ) ;
4740 }
48-
49- public async downloadLanguageServer ( context : IExtensionContext ) : Promise < void > {
41+ public async downloadLanguageServer ( destinationFolder : string ) : Promise < void > {
5042 const downloadInfo = await this . getDownloadInfo ( ) ;
5143 const downloadUri = downloadInfo . uri ;
5244 const lsVersion = downloadInfo . version . raw ;
@@ -61,7 +53,7 @@ export class LanguageServerDownloader implements ILanguageServerDownloader {
6153 this . output . appendLine ( err ) ;
6254 success = false ;
6355 this . appShell . showErrorMessage ( LanguageService . lsFailedToDownload ( ) ) ;
64- sendTelemetryEvent ( PYTHON_LANGUAGE_SERVER_ERROR , undefined , { error : 'Failed to download (platform)' } ) ;
56+ sendTelemetryEvent ( PYTHON_LANGUAGE_SERVER_ERROR , undefined , { error : 'Failed to download (platform)' } , err ) ;
6557 throw new Error ( err ) ;
6658 } finally {
6759 sendTelemetryEvent (
@@ -73,13 +65,13 @@ export class LanguageServerDownloader implements ILanguageServerDownloader {
7365
7466 timer . reset ( ) ;
7567 try {
76- await this . unpackArchive ( context . extensionPath , localTempFilePath ) ;
68+ await this . unpackArchive ( destinationFolder , localTempFilePath ) ;
7769 } catch ( err ) {
7870 this . output . appendLine ( 'extraction failed.' ) ;
7971 this . output . appendLine ( err ) ;
8072 success = false ;
8173 this . appShell . showErrorMessage ( LanguageService . lsFailedToExtract ( ) ) ;
82- sendTelemetryEvent ( PYTHON_LANGUAGE_SERVER_ERROR , undefined , { error : 'Failed to extract (platform)' } ) ;
74+ sendTelemetryEvent ( PYTHON_LANGUAGE_SERVER_ERROR , undefined , { error : 'Failed to extract (platform)' } , err ) ;
8375 throw new Error ( err ) ;
8476 } finally {
8577 sendTelemetryEvent (
@@ -107,11 +99,12 @@ export class LanguageServerDownloader implements ILanguageServerDownloader {
10799 await window . withProgress ( {
108100 location : ProgressLocation . Window
109101 } , async ( progress ) => {
110- const httpClient = this . serviceContainer . get < IHttpClient > ( IHttpClient ) ;
111- const req = await httpClient . downloadFile ( uri ) ;
102+ const req = await this . httpClient . downloadFile ( uri ) ;
112103 req . on ( 'response' , ( response ) => {
113104 if ( response . statusCode !== 200 ) {
114- throw new Error ( `Failed with status ${ response . statusCode } , ${ response . statusMessage } , Uri ${ uri } ` ) ;
105+ const error = new Error ( `Failed with status ${ response . statusCode } , ${ response . statusMessage } , Uri ${ uri } ` ) ;
106+ deferred . reject ( error ) ;
107+ throw error ;
115108 }
116109 } ) ;
117110 const requestProgress = await import ( 'request-progress' ) ;
@@ -139,10 +132,9 @@ export class LanguageServerDownloader implements ILanguageServerDownloader {
139132 return tempFile . filePath ;
140133 }
141134
142- protected async unpackArchive ( extensionPath : string , tempFilePath : string ) : Promise < void > {
135+ protected async unpackArchive ( destinationFolder : string , tempFilePath : string ) : Promise < void > {
143136 this . output . append ( 'Unpacking archive... ' ) ;
144137
145- const installFolder = path . join ( extensionPath , this . engineFolder ) ;
146138 const deferred = createDeferred ( ) ;
147139
148140 const title = 'Extracting files... ' ;
@@ -160,10 +152,10 @@ export class LanguageServerDownloader implements ILanguageServerDownloader {
160152 let extractedFiles = 0 ;
161153 zip . on ( 'ready' , async ( ) => {
162154 totalFiles = zip . entriesCount ;
163- if ( ! await this . fs . directoryExists ( installFolder ) ) {
164- await this . fs . createDirectory ( installFolder ) ;
155+ if ( ! await this . fs . directoryExists ( destinationFolder ) ) {
156+ await this . fs . createDirectory ( destinationFolder ) ;
165157 }
166- zip . extract ( null , installFolder , ( err ) => {
158+ zip . extract ( null , destinationFolder , ( err ) => {
167159 if ( err ) {
168160 deferred . reject ( err ) ;
169161 } else {
@@ -181,7 +173,7 @@ export class LanguageServerDownloader implements ILanguageServerDownloader {
181173 } ) ;
182174
183175 // Set file to executable (nothing happens in Windows, as chmod has no definition there)
184- const executablePath = path . join ( installFolder , this . platformData . getEngineExecutableName ( ) ) ;
176+ const executablePath = path . join ( destinationFolder , this . platformData . engineExecutableName ) ;
185177 await this . fs . chmod ( executablePath , '0764' ) ; // -rwxrw-r--
186178
187179 this . output . appendLine ( 'done.' ) ;
0 commit comments