import * as https from 'https' ; import * as fs from 'fs' ; import * as path from 'path' ; import * as cp from 'child_process' ; import { parse as parseUrl } from 'url' ; function ensureFolderExists ( loc ) { if ( ! fs . existsSync ( loc ) ) { const parent = path . dirname ( loc ) ; if ( parent ) { ensureFolderExists ( parent ) ; } fs . mkdirSync ( loc ) ; } } function getDownloadUrl ( updateUrl , commit , platform , quality ) { return `${ updateUrl }/commit:${ commit }/server-${ platform }/${ quality }` ; } async function downloadVSCodeServerArchive ( updateUrl , commit , quality , destDir , log ) { ensureFolderExists ( destDir ) ; const platform = process . platform === 'win32' ? 'win32-x64' : process . platform === 'darwin' ? 'darwin' : 'linux-x64' ; const downloadUrl = getDownloadUrl ( updateUrl , commit , platform , quality ) ; return new Promise ( ( resolve , reject ) => { log ( `Downloading VS Code Server from: ${ downloadUrl }` ) ; const requestOptions = parseUrl ( downloadUrl ) ; https . get ( requestOptions , res => { if ( res . statusCode !== 302 ) { reject ( 'Failed to get VS Code server archive location' ) ; } const archiveUrl = res . headers . location ; if ( ! archiveUrl ) { reject ( 'Failed to get VS Code server archive location' ) ; return ; } const archiveRequestOptions = parseUrl ( archiveUrl ) ; if ( archiveUrl . endsWith ( '.zip' ) ) { const archivePath = path . resolve ( destDir , `vscode-server-${ commit }.zip` ) ; const outStream = fs . createWriteStream ( archivePath ) ; outStream . on ( 'close' , ( ) => { resolve ( archivePath ) ; } ) ; https . get ( archiveRequestOptions , res => { res . pipe ( outStream ) ; } ) ; } else { const zipPath = path . resolve ( destDir , `vscode-server-${ commit }.tgz` ) ; const outStream = fs . createWriteStream ( zipPath ) ; https . get ( archiveRequestOptions , res => { res . pipe ( outStream ) ; } ) ; outStream . on ( 'close' , ( ) => { resolve ( zipPath ) ; } ) ; } } ) ; } ) ; } /**
 * Unzip a .zip or .tar.gz VS Code archive
 */ function unzipVSCodeServer ( vscodeArchivePath , extractDir , destDir , log ) { log ( `Extracting ${ vscodeArchivePath }` ) ; if ( vscodeArchivePath . endsWith ( '.zip' ) ) { const tempDir = fs . mkdtempSync ( path . join ( destDir , 'vscode-server-extract' ) ) ; if ( process . platform === 'win32' ) { cp . spawnSync ( 'powershell.exe' , [ '-NoProfile' , '-ExecutionPolicy' , 'Bypass' , '-NonInteractive' , '-NoLogo' , '-Command' , `Microsoft.PowerShell.Archive\\Expand-Archive -Path "${ vscodeArchivePath }" -DestinationPath "${ tempDir }"` ] ) ; } else { cp . spawnSync ( 'unzip' , [ vscodeArchivePath , '-d' , `${ tempDir }` ] ) ; } fs . renameSync ( path . join ( tempDir , process . platform === 'win32' ? 'vscode-server-win32-x64' : 'vscode-server-darwin' ) , extractDir ) ; } else { if ( ! fs . existsSync ( extractDir ) ) { fs . mkdirSync ( extractDir ) ; } cp . spawnSync ( 'tar' , [ '-xzf' , vscodeArchivePath , '-C' , extractDir , '--strip-components' , '1' ] ) ; } } export async function downloadAndUnzipVSCodeServer ( updateUrl , commit , quality = 'stable' , destDir , log ) { const extractDir = path . join ( destDir , commit ) ; if ( fs . existsSync ( extractDir ) ) { log ( `Found ${ extractDir }. Skipping download.` ) ; } else { log ( `Downloading VS Code Server ${ quality } - ${ commit } into ${ extractDir }.` ) ; try { const vscodeArchivePath = await downloadVSCodeServerArchive ( updateUrl , commit , quality , destDir , log ) ; if ( fs . existsSync ( vscodeArchivePath ) ) { unzipVSCodeServer ( vscodeArchivePath , extractDir , destDir , log ) ; fs . unlinkSync ( vscodeArchivePath ) ; } } catch ( err ) { throw Error ( `Failed to download and unzip VS Code ${ quality } - ${ commit }` ) ; } } return Promise . resolve ( extractDir ) ; }