@vscode/test-electron
Advanced tools
Comparing version 2.0.3 to 2.1.0-beta.0
# Changelog | ||
### 2.1.0 | 2021-01-14 | ||
- Add a progress `reporter` option on the `TestOptions`, which can be used to see more detail or silence download progress. | ||
### 2.0.3 | 2021-01-11 | ||
@@ -4,0 +8,0 @@ |
@@ -0,1 +1,2 @@ | ||
import { ProgressReporter } from './progress'; | ||
/** | ||
@@ -18,2 +19,4 @@ * Adapted from https://github.com/microsoft/TypeScript/issues/29729 | ||
readonly architecture: DownloadArchitecture; | ||
readonly reporter?: ProgressReporter; | ||
readonly extractSync?: boolean; | ||
} | ||
@@ -40,3 +43,4 @@ export declare const defaultCachePath: string; | ||
*/ | ||
export declare function downloadAndUnzipVSCode(version?: DownloadVersion, platform?: DownloadPlatform): Promise<string>; | ||
export declare function downloadAndUnzipVSCode(options: Partial<DownloadOptions>): Promise<string>; | ||
export declare function downloadAndUnzipVSCode(version?: DownloadVersion, platform?: DownloadPlatform, reporter?: ProgressReporter, extractSync?: boolean): Promise<string>; | ||
export {}; |
@@ -8,12 +8,13 @@ "use strict"; | ||
exports.downloadAndUnzipVSCode = exports.download = exports.defaultCachePath = void 0; | ||
const cp = require("child_process"); | ||
const fs = require("fs"); | ||
const os_1 = require("os"); | ||
const path = require("path"); | ||
const cp = require("child_process"); | ||
const stream_1 = require("stream"); | ||
const unzipper_1 = require("unzipper"); | ||
const util_1 = require("util"); | ||
const del = require("./del"); | ||
const progress_1 = require("./progress"); | ||
const request = require("./request"); | ||
const del = require("./del"); | ||
const util_1 = require("./util"); | ||
const unzipper_1 = require("unzipper"); | ||
const stream_1 = require("stream"); | ||
const os_1 = require("os"); | ||
const util_2 = require("util"); | ||
const util_2 = require("./util"); | ||
const extensionRoot = process.cwd(); | ||
@@ -40,8 +41,8 @@ const vscodeStableReleasesAPI = `https://update.code.visualstudio.com/api/releases/stable`; | ||
async function downloadVSCodeArchive(options) { | ||
var _a, _b; | ||
if (!fs.existsSync(options.cachePath)) { | ||
fs.mkdirSync(options.cachePath); | ||
} | ||
const downloadUrl = util_1.getVSCodeDownloadUrl(options.version, options.platform, options.architecture); | ||
const text = `Downloading VS Code ${options.version} from ${downloadUrl}`; | ||
process.stdout.write(text); | ||
const downloadUrl = util_2.getVSCodeDownloadUrl(options.version, options.platform, options.architecture); | ||
(_a = options.reporter) === null || _a === void 0 ? void 0 : _a.report({ stage: progress_1.ProgressReportStage.ResolvingCDNLocation, url: downloadUrl }); | ||
const res = await request.getStream(downloadUrl); | ||
@@ -51,36 +52,21 @@ if (res.statusCode !== 302) { | ||
} | ||
const archiveUrl = res.headers.location; | ||
if (!archiveUrl) { | ||
const url = res.headers.location; | ||
if (!url) { | ||
throw 'Failed to get VS Code archive location'; | ||
} | ||
const download = await request.getStream(archiveUrl); | ||
printProgress(text, download); | ||
return { stream: download, format: archiveUrl.endsWith('.zip') ? 'zip' : 'tgz' }; | ||
} | ||
function printProgress(baseText, res) { | ||
if (!process.stdout.isTTY) { | ||
return; | ||
} | ||
const total = Number(res.headers['content-length']); | ||
let received = 0; | ||
let timeout; | ||
const reset = '\x1b[G\x1b[0K'; | ||
res.on('data', chunk => { | ||
if (!timeout) { | ||
timeout = setTimeout(() => { | ||
process.stdout.write(`${reset}${baseText}: ${received}/${total} (${(received / total * 100).toFixed()}%)`); | ||
timeout = undefined; | ||
}, 100); | ||
} | ||
received += chunk.length; | ||
res.destroy(); | ||
const download = await request.getStream(url); | ||
const totalBytes = Number(download.headers['content-length']); | ||
(_b = options.reporter) === null || _b === void 0 ? void 0 : _b.report({ stage: progress_1.ProgressReportStage.Downloading, url, bytesSoFar: 0, totalBytes }); | ||
let bytesSoFar = 0; | ||
download.on('data', chunk => { | ||
var _a; | ||
bytesSoFar += chunk.length; | ||
(_a = options.reporter) === null || _a === void 0 ? void 0 : _a.report({ stage: progress_1.ProgressReportStage.Downloading, url, bytesSoFar, totalBytes }); | ||
}); | ||
res.on('end', () => { | ||
if (timeout) { | ||
clearTimeout(timeout); | ||
} | ||
console.log(`${reset}${baseText}: complete`); | ||
download.on('end', () => { | ||
var _a; | ||
(_a = options.reporter) === null || _a === void 0 ? void 0 : _a.report({ stage: progress_1.ProgressReportStage.Downloading, url, bytesSoFar: totalBytes, totalBytes }); | ||
}); | ||
res.on('error', err => { | ||
throw err; | ||
}); | ||
return { stream: download, format: url.endsWith('.zip') ? 'zip' : 'tgz' }; | ||
} | ||
@@ -90,3 +76,4 @@ /** | ||
*/ | ||
async function unzipVSCode(extractDir, stream, format) { | ||
async function unzipVSCode(reporter, extractDir, extractSync, stream, format) { | ||
const stagingFile = path.join(os_1.tmpdir(), `vscode-test-${Date.now()}.zip`); | ||
if (format === 'zip') { | ||
@@ -100,3 +87,16 @@ // note: this used to use Expand-Archive, but this caused a failure | ||
// - https://github.com/ZJONSSON/node-unzipper/issues/115 (not avoidable) | ||
if (process.platform !== 'darwin') { | ||
if (process.platform === 'win32' && extractSync) { | ||
try { | ||
await util_1.promisify(stream_1.pipeline)(stream, fs.createWriteStream(stagingFile)); | ||
reporter.report({ stage: progress_1.ProgressReportStage.ExtractingSynchonrously }); | ||
await spawnDecompressorChild('powershell.exe', [ | ||
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-NonInteractive', '-NoLogo', | ||
'-Command', `Microsoft.PowerShell.Archive\\Expand-Archive -Path "${stagingFile}" -DestinationPath "${extractDir}"` | ||
]); | ||
} | ||
finally { | ||
fs.unlink(stagingFile, () => undefined); | ||
} | ||
} | ||
else if (process.platform !== 'darwin' && !extractSync) { | ||
await new Promise((resolve, reject) => stream | ||
@@ -107,10 +107,10 @@ .pipe(unzipper_1.Extract({ path: extractDir })) | ||
} | ||
else { | ||
const stagingFile = path.join(os_1.tmpdir(), `vscode-test-${Date.now()}.zip`); | ||
else { // darwin or *nix sync | ||
try { | ||
await util_2.promisify(stream_1.pipeline)(stream, fs.createWriteStream(stagingFile)); | ||
await util_1.promisify(stream_1.pipeline)(stream, fs.createWriteStream(stagingFile)); | ||
reporter.report({ stage: progress_1.ProgressReportStage.ExtractingSynchonrously }); | ||
await spawnDecompressorChild('unzip', ['-q', stagingFile, '-d', extractDir]); | ||
} | ||
finally { | ||
// fs.unlink(stagingFile, () => undefined); | ||
fs.unlink(stagingFile, () => undefined); | ||
} | ||
@@ -142,8 +142,5 @@ } | ||
*/ | ||
async function download(options) { | ||
var _a, _b, _c; | ||
async function download(options = {}) { | ||
let version = options === null || options === void 0 ? void 0 : options.version; | ||
const platform = (_a = options === null || options === void 0 ? void 0 : options.platform) !== null && _a !== void 0 ? _a : util_1.systemDefaultPlatform; | ||
const architecture = (_b = options === null || options === void 0 ? void 0 : options.architecture) !== null && _b !== void 0 ? _b : util_1.systemDefaultArchitecture; | ||
const cachePath = (_c = options === null || options === void 0 ? void 0 : options.cachePath) !== null && _c !== void 0 ? _c : exports.defaultCachePath; | ||
const { platform = util_2.systemDefaultPlatform, architecture = util_2.systemDefaultArchitecture, cachePath = exports.defaultCachePath, reporter = new progress_1.ConsoleReporter(process.stdout.isTTY), extractSync = false, } = options; | ||
if (version) { | ||
@@ -167,21 +164,27 @@ if (version === 'stable') { | ||
} | ||
reporter.report({ stage: progress_1.ProgressReportStage.ResolvedVersion, version }); | ||
const downloadedPath = path.resolve(cachePath, `vscode-${platform}-${version}`); | ||
if (fs.existsSync(downloadedPath)) { | ||
if (version === 'insiders') { | ||
const { version: currentHash, date: currentDate } = util_1.insidersDownloadDirMetadata(downloadedPath); | ||
const { version: latestHash, timestamp: latestTimestamp } = await util_1.getLatestInsidersMetadata(util_1.systemDefaultPlatform); | ||
reporter.report({ stage: progress_1.ProgressReportStage.FetchingInsidersMetadata }); | ||
const { version: currentHash, date: currentDate } = util_2.insidersDownloadDirMetadata(downloadedPath); | ||
const { version: latestHash, timestamp: latestTimestamp } = await util_2.getLatestInsidersMetadata(util_2.systemDefaultPlatform); | ||
if (currentHash === latestHash) { | ||
console.log(`Found insiders matching latest Insiders release. Skipping download.`); | ||
return Promise.resolve(util_1.insidersDownloadDirToExecutablePath(downloadedPath)); | ||
reporter.report({ stage: progress_1.ProgressReportStage.FoundMatchingInstall, downloadedPath }); | ||
return Promise.resolve(util_2.insidersDownloadDirToExecutablePath(downloadedPath)); | ||
} | ||
else { | ||
try { | ||
console.log(`Remove outdated Insiders at ${downloadedPath} and re-downloading.`); | ||
console.log(`Old: ${currentHash} | ${currentDate}`); | ||
console.log(`New: ${latestHash} | ${new Date(latestTimestamp).toISOString()}`); | ||
reporter.report({ | ||
stage: progress_1.ProgressReportStage.ReplacingOldInsiders, | ||
downloadedPath, | ||
oldDate: currentDate, | ||
oldHash: currentHash, | ||
newDate: new Date(latestTimestamp), | ||
newHash: latestHash, | ||
}); | ||
await del.rmdir(downloadedPath); | ||
console.log(`Removed ${downloadedPath}`); | ||
} | ||
catch (err) { | ||
console.error(err); | ||
reporter.error(err); | ||
throw Error(`Failed to remove outdated Insiders at ${downloadedPath}.`); | ||
@@ -192,40 +195,28 @@ } | ||
else { | ||
console.log(`Found ${downloadedPath}. Skipping download.`); | ||
return Promise.resolve(util_1.downloadDirToExecutablePath(downloadedPath)); | ||
reporter.report({ stage: progress_1.ProgressReportStage.FoundMatchingInstall, downloadedPath }); | ||
return Promise.resolve(util_2.downloadDirToExecutablePath(downloadedPath)); | ||
} | ||
} | ||
try { | ||
const { stream, format } = await downloadVSCodeArchive({ version, architecture, platform, cachePath }); | ||
await unzipVSCode(downloadedPath, stream, format); | ||
console.log(`Downloaded VS Code ${version} into ${downloadedPath}`); | ||
const { stream, format } = await downloadVSCodeArchive({ version, architecture, platform, cachePath, reporter }); | ||
await unzipVSCode(reporter, downloadedPath, extractSync, stream, format); | ||
reporter.report({ stage: progress_1.ProgressReportStage.NewInstallComplete, downloadedPath }); | ||
} | ||
catch (err) { | ||
console.error(err); | ||
reporter.error(err); | ||
throw Error(`Failed to download and unzip VS Code ${version}`); | ||
} | ||
if (version === 'insiders') { | ||
return Promise.resolve(util_1.insidersDownloadDirToExecutablePath(downloadedPath)); | ||
return Promise.resolve(util_2.insidersDownloadDirToExecutablePath(downloadedPath)); | ||
} | ||
else { | ||
return util_1.downloadDirToExecutablePath(downloadedPath); | ||
return util_2.downloadDirToExecutablePath(downloadedPath); | ||
} | ||
} | ||
exports.download = download; | ||
/** | ||
* Download and unzip a copy of VS Code in `.vscode-test`. The paths are: | ||
* - `.vscode-test/vscode-<PLATFORM>-<VERSION>`. For example, `./vscode-test/vscode-win32-1.32.0` | ||
* - `.vscode-test/vscode-win32-insiders`. | ||
* | ||
* *If a local copy exists at `.vscode-test/vscode-<PLATFORM>-<VERSION>`, skip download.* | ||
* | ||
* @param version The version of VS Code to download such as `1.32.0`. You can also use | ||
* `'stable'` for downloading latest stable release. | ||
* `'insiders'` for downloading latest Insiders. | ||
* When unspecified, download latest stable version. | ||
* | ||
* @returns Promise of `vscodeExecutablePath`. | ||
*/ | ||
async function downloadAndUnzipVSCode(version, platform = util_1.systemDefaultPlatform) { | ||
return await download({ version, platform }); | ||
async function downloadAndUnzipVSCode(versionOrOptions, platform, reporter, extractSync) { | ||
return await download(typeof versionOrOptions === 'object' | ||
? versionOrOptions | ||
: { version: versionOrOptions, platform, reporter, extractSync }); | ||
} | ||
exports.downloadAndUnzipVSCode = downloadAndUnzipVSCode; |
export { download, downloadAndUnzipVSCode } from './download'; | ||
export { runTests } from './runTest'; | ||
export { resolveCliPathFromVSCodeExecutablePath, resolveCliArgsFromVSCodeExecutablePath } from './util'; | ||
export * from './progress'; |
@@ -6,2 +6,12 @@ "use strict"; | ||
*--------------------------------------------------------------------------------------------*/ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -17,1 +27,2 @@ exports.resolveCliArgsFromVSCodeExecutablePath = exports.resolveCliPathFromVSCodeExecutablePath = exports.runTests = exports.downloadAndUnzipVSCode = exports.download = void 0; | ||
Object.defineProperty(exports, "resolveCliArgsFromVSCodeExecutablePath", { enumerable: true, get: function () { return util_1.resolveCliArgsFromVSCodeExecutablePath; } }); | ||
__exportStar(require("./progress"), exports); |
import { DownloadVersion, DownloadPlatform } from './download'; | ||
import { ProgressReporter } from './progress'; | ||
export interface TestOptions { | ||
@@ -74,2 +75,13 @@ /** | ||
launchArgs?: string[]; | ||
/** | ||
* Progress reporter to use while VS Code is downloaded. Defaults to a | ||
* console reporter. A {@link SilentReporter} is also available, and you | ||
* may implement your own. | ||
*/ | ||
reporter?: ProgressReporter; | ||
/** | ||
* Whether the downloaded zip should be synchronously extracted. Should be | ||
* omitted unless you're experiencing issues installing VS Code versions. | ||
*/ | ||
extractSync?: boolean; | ||
} | ||
@@ -76,0 +88,0 @@ /** |
@@ -18,3 +18,3 @@ "use strict"; | ||
if (!options.vscodeExecutablePath) { | ||
options.vscodeExecutablePath = await download_1.downloadAndUnzipVSCode(options.version, options.platform); | ||
options.vscodeExecutablePath = await download_1.downloadAndUnzipVSCode(options); | ||
} | ||
@@ -21,0 +21,0 @@ let args = [ |
@@ -13,3 +13,3 @@ /// <reference types="node" /> | ||
version: any; | ||
date: any; | ||
date: Date; | ||
}; | ||
@@ -16,0 +16,0 @@ export interface IUpdateMetadata { |
@@ -108,3 +108,3 @@ "use strict"; | ||
version: productJson.commit, | ||
date: productJson.date | ||
date: new Date(productJson.date) | ||
}; | ||
@@ -111,0 +111,0 @@ } |
{ | ||
"name": "@vscode/test-electron", | ||
"version": "2.0.3", | ||
"version": "2.1.0-beta.0", | ||
"scripts": { | ||
@@ -5,0 +5,0 @@ "compile": "tsc -p ./", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56300
22
948
2