diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 1da37657bb95a..a682ddd9d25f8 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -34,6 +34,7 @@ const i18n = require('./lib/i18n'); const glob = require('glob'); const deps = require('./dependencies'); const getElectronVersion = require('./lib/electron').getElectronVersion; +const createAsar = require('./lib/asar').createAsar; const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname)); const baseModules = Object.keys(process.binding('natives')).filter(n => !/^_|\//.test(n)); @@ -303,7 +304,8 @@ function packageTask(platform, arch, opts) { .pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/**'])) .pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a'])) - .pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node'])); + .pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node'])) + .pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*'], 'app/node_modules.asar')); let all = es.merge( packageJsonStream, diff --git a/build/lib/asar.js b/build/lib/asar.js new file mode 100644 index 0000000000000..cd961e2a6de38 --- /dev/null +++ b/build/lib/asar.js @@ -0,0 +1,118 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +var path = require("path"); +var es = require("event-stream"); +var pickle = require("chromium-pickle-js"); +var Filesystem = require("asar/lib/filesystem"); +var VinylFile = require("vinyl"); +var minimatch = require("minimatch"); +function createAsar(folderPath, unpackGlobs, destFilename) { + var shouldUnpackFile = function (file) { + for (var i = 0; i < unpackGlobs.length; i++) { + if (minimatch(file.relative, unpackGlobs[i])) { + return true; + } + } + return false; + }; + var filesystem = new Filesystem(folderPath); + var out = []; + // Keep track of pending inserts + var pendingInserts = 0; + var onFileInserted = function () { pendingInserts--; }; + // Do not insert twice the same directory + var seenDir = {}; + var insertDirectoryRecursive = function (dir) { + if (seenDir[dir]) { + return; + } + var lastSlash = dir.lastIndexOf('/'); + if (lastSlash === -1) { + lastSlash = dir.lastIndexOf('\\'); + } + if (lastSlash !== -1) { + insertDirectoryRecursive(dir.substring(0, lastSlash)); + } + seenDir[dir] = true; + filesystem.insertDirectory(dir); + }; + var insertDirectoryForFile = function (file) { + var lastSlash = file.lastIndexOf('/'); + if (lastSlash === -1) { + lastSlash = file.lastIndexOf('\\'); + } + if (lastSlash !== -1) { + insertDirectoryRecursive(file.substring(0, lastSlash)); + } + }; + var insertFile = function (relativePath, stat, shouldUnpack) { + insertDirectoryForFile(relativePath); + pendingInserts++; + filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted); + }; + return es.through(function (file) { + if (file.stat.isDirectory()) { + return; + } + if (!file.stat.isFile()) { + throw new Error("unknown item in stream!"); + } + var shouldUnpack = shouldUnpackFile(file); + insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack); + if (shouldUnpack) { + // The file goes outside of xx.asar, in a folder xx.asar.unpacked + var relative = path.relative(folderPath, file.path); + this.queue(new VinylFile({ + cwd: folderPath, + base: folderPath, + path: path.join(destFilename + '.unpacked', relative), + stat: file.stat, + contents: file.contents + })); + } + else { + // The file goes inside of xx.asar + out.push(file.contents); + } + }, function () { + var _this = this; + var finish = function () { + { + var headerPickle = pickle.createEmpty(); + headerPickle.writeString(JSON.stringify(filesystem.header)); + var headerBuf = headerPickle.toBuffer(); + var sizePickle = pickle.createEmpty(); + sizePickle.writeUInt32(headerBuf.length); + var sizeBuf = sizePickle.toBuffer(); + out.unshift(headerBuf); + out.unshift(sizeBuf); + } + var contents = Buffer.concat(out); + out.length = 0; + _this.queue(new VinylFile({ + cwd: folderPath, + base: folderPath, + path: destFilename, + contents: contents + })); + _this.queue(null); + }; + // Call finish() only when all file inserts have finished... + if (pendingInserts === 0) { + finish(); + } + else { + onFileInserted = function () { + pendingInserts--; + if (pendingInserts === 0) { + finish(); + } + }; + } + }); +} +exports.createAsar = createAsar; diff --git a/build/lib/asar.ts b/build/lib/asar.ts new file mode 100644 index 0000000000000..c4a93a3e53333 --- /dev/null +++ b/build/lib/asar.ts @@ -0,0 +1,131 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as path from 'path'; +import * as es from 'event-stream'; +import * as pickle from 'chromium-pickle-js'; +import * as Filesystem from 'asar/lib/filesystem'; +import * as VinylFile from 'vinyl'; +import * as minimatch from 'minimatch'; + +export function createAsar(folderPath: string, unpackGlobs: string[], destFilename: string): NodeJS.ReadWriteStream { + + const shouldUnpackFile = (file: VinylFile): boolean => { + for (let i = 0; i < unpackGlobs.length; i++) { + if (minimatch(file.relative, unpackGlobs[i])) { + return true; + } + } + return false; + }; + + const filesystem = new Filesystem(folderPath); + const out: Buffer[] = []; + + // Keep track of pending inserts + let pendingInserts = 0; + let onFileInserted = () => { pendingInserts--; }; + + // Do not insert twice the same directory + const seenDir: { [key: string]: boolean; } = {}; + const insertDirectoryRecursive = (dir: string) => { + if (seenDir[dir]) { + return; + } + + let lastSlash = dir.lastIndexOf('/'); + if (lastSlash === -1) { + lastSlash = dir.lastIndexOf('\\'); + } + if (lastSlash !== -1) { + insertDirectoryRecursive(dir.substring(0, lastSlash)); + } + seenDir[dir] = true; + filesystem.insertDirectory(dir); + }; + + const insertDirectoryForFile = (file: string) => { + let lastSlash = file.lastIndexOf('/'); + if (lastSlash === -1) { + lastSlash = file.lastIndexOf('\\'); + } + if (lastSlash !== -1) { + insertDirectoryRecursive(file.substring(0, lastSlash)); + } + }; + + const insertFile = (relativePath: string, stat: { size: number; mode: number; }, shouldUnpack: boolean) => { + insertDirectoryForFile(relativePath); + pendingInserts++; + filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted); + }; + + return es.through(function (file) { + if (file.stat.isDirectory()) { + return; + } + if (!file.stat.isFile()) { + throw new Error(`unknown item in stream!`); + } + const shouldUnpack = shouldUnpackFile(file); + insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack); + + if (shouldUnpack) { + // The file goes outside of xx.asar, in a folder xx.asar.unpacked + const relative = path.relative(folderPath, file.path); + this.queue(new VinylFile({ + cwd: folderPath, + base: folderPath, + path: path.join(destFilename + '.unpacked', relative), + stat: file.stat, + contents: file.contents + })); + } else { + // The file goes inside of xx.asar + out.push(file.contents); + } + }, function () { + + let finish = () => { + { + const headerPickle = pickle.createEmpty(); + headerPickle.writeString(JSON.stringify(filesystem.header)); + const headerBuf = headerPickle.toBuffer(); + + const sizePickle = pickle.createEmpty(); + sizePickle.writeUInt32(headerBuf.length); + const sizeBuf = sizePickle.toBuffer(); + + out.unshift(headerBuf); + out.unshift(sizeBuf); + } + + const contents = Buffer.concat(out); + out.length = 0; + + this.queue(new VinylFile({ + cwd: folderPath, + base: folderPath, + path: destFilename, + contents: contents + })); + this.queue(null); + }; + + // Call finish() only when all file inserts have finished... + if (pendingInserts === 0) { + finish(); + } else { + onFileInserted = () => { + pendingInserts--; + if (pendingInserts === 0) { + finish(); + } + }; + } + }); +} diff --git a/package.json b/package.json index 51176c67d9333..1407c9e384bbb 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,9 @@ "@types/minimist": "1.2.0", "@types/mocha": "2.2.39", "@types/sinon": "1.16.34", + "asar": "^0.14.0", "azure-storage": "^0.3.1", + "chromium-pickle-js": "^0.2.0", "clean-css": "3.4.6", "coveralls": "^2.11.11", "cson-parser": "^1.3.3", diff --git a/src/bootstrap.js b/src/bootstrap.js index af713da7509a5..5d7c3bf61f5a1 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -3,10 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// disable electron's asar support early on because bootstrap.js is used in forked processes -// where the environment is purely node based. this will instruct electron to not treat files -// with *.asar ending any special from normal files. -process.noAsar = true; +//#region Add support for using node_modules.asar +(function () { + const path = require('path'); + const Module = require('module'); + const NODE_MODULES_PATH = path.join(__dirname, '../node_modules'); + const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; + + const originalResolveLookupPaths = Module._resolveLookupPaths; + Module._resolveLookupPaths = function (request, parent) { + const result = originalResolveLookupPaths(request, parent); + + const paths = result[1]; + for (let i = 0, len = paths.length; i < len; i++) { + if (paths[i] === NODE_MODULES_PATH) { + paths.splice(i, 0, NODE_MODULES_ASAR_PATH); + break; + } + } + + return result; + }; +})(); +//#endregion // Will be defined if we got forked from another node process // In that case we override console.log/warn/error to be able diff --git a/src/main.js b/src/main.js index 127e6500797f5..e92627112c745 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,30 @@ perf.mark('main:started'); // Perf measurements global.perfStartTime = Date.now(); +//#region Add support for using node_modules.asar +(function () { + const path = require('path'); + const Module = require('module'); + const NODE_MODULES_PATH = path.join(__dirname, '../node_modules'); + const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; + + const originalResolveLookupPaths = Module._resolveLookupPaths; + Module._resolveLookupPaths = function (request, parent) { + const result = originalResolveLookupPaths(request, parent); + + const paths = result[1]; + for (let i = 0, len = paths.length; i < len; i++) { + if (paths[i] === NODE_MODULES_PATH) { + paths.splice(i, 0, NODE_MODULES_ASAR_PATH); + break; + } + } + + return result; + }; +})(); +//#endregion + let app = require('electron').app; let fs = require('fs'); let path = require('path'); diff --git a/src/vs/base/node/stdFork.ts b/src/vs/base/node/stdFork.ts index 83dc15268ab41..1bdcd138309af 100644 --- a/src/vs/base/node/stdFork.ts +++ b/src/vs/base/node/stdFork.ts @@ -50,7 +50,6 @@ function generatePatchedEnv(env: any, stdInPipeName: string, stdOutPipeName: str newEnv['STDOUT_PIPE_NAME'] = stdOutPipeName; newEnv['STDERR_PIPE_NAME'] = stdErrPipeName; newEnv['ELECTRON_RUN_AS_NODE'] = '1'; - newEnv['ELECTRON_NO_ASAR'] = '1'; return newEnv; } @@ -138,4 +137,4 @@ export function fork(modulePath: string, args: string[], options: IForkOpts, cal // On vscode exit still close server #7758 process.once('exit', closeServer); -} \ No newline at end of file +} diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcess.js b/src/vs/code/electron-browser/sharedProcess/sharedProcess.js index 94481666801a6..b4e968d799012 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcess.js +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcess.js @@ -57,6 +57,34 @@ function main() { const args = parseURLQueryArgs(); const configuration = JSON.parse(args['config'] || '{}') || {}; + //#region Add support for using node_modules.asar + (function () { + const path = require('path'); + const Module = require('module'); + let NODE_MODULES_PATH = path.join(configuration.appRoot, 'node_modules'); + if (/[a-z]\:/.test(NODE_MODULES_PATH)) { + // Make drive letter uppercase + NODE_MODULES_PATH = NODE_MODULES_PATH.charAt(0).toUpperCase() + NODE_MODULES_PATH.substr(1); + } + const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; + + const originalResolveLookupPaths = Module._resolveLookupPaths; + Module._resolveLookupPaths = function (request, parent) { + const result = originalResolveLookupPaths(request, parent); + + const paths = result[1]; + for (let i = 0, len = paths.length; i < len; i++) { + if (paths[i] === NODE_MODULES_PATH) { + paths.splice(i, 0, NODE_MODULES_ASAR_PATH); + break; + } + } + + return result; + }; + })(); + //#endregion + // Correctly inherit the parent's environment assign(process.env, configuration.userEnv); @@ -84,7 +112,7 @@ function main() { bundles[bundle] = json; cb(undefined, json); }) - .catch(cb); + .catch(cb); }; } diff --git a/src/vs/workbench/electron-browser/bootstrap/index.js b/src/vs/workbench/electron-browser/bootstrap/index.js index 558e8df307e9a..a933a9fc4c2fc 100644 --- a/src/vs/workbench/electron-browser/bootstrap/index.js +++ b/src/vs/workbench/electron-browser/bootstrap/index.js @@ -123,6 +123,34 @@ function main() { const args = parseURLQueryArgs(); const configuration = JSON.parse(args['config'] || '{}') || {}; + //#region Add support for using node_modules.asar + (function () { + const path = require('path'); + const Module = require('module'); + let NODE_MODULES_PATH = path.join(configuration.appRoot, 'node_modules'); + if (/[a-z]\:/.test(NODE_MODULES_PATH)) { + // Make drive letter uppercase + NODE_MODULES_PATH = NODE_MODULES_PATH.charAt(0).toUpperCase() + NODE_MODULES_PATH.substr(1); + } + const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar'; + + const originalResolveLookupPaths = Module._resolveLookupPaths; + Module._resolveLookupPaths = function (request, parent) { + const result = originalResolveLookupPaths(request, parent); + + const paths = result[1]; + for (let i = 0, len = paths.length; i < len; i++) { + if (paths[i] === NODE_MODULES_PATH) { + paths.splice(i, 0, NODE_MODULES_ASAR_PATH); + break; + } + } + + return result; + }; + })(); + //#endregion + // Correctly inherit the parent's environment assign(process.env, configuration.userEnv); perf.importEntries(configuration.perfEntries); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index cb7cb3d37fde8..8079fd1e19837 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -144,7 +144,6 @@ export class ExtensionHostProcessWorker { VSCODE_WINDOW_ID: String(this._windowService.getCurrentWindowId()), VSCODE_IPC_HOOK_EXTHOST: pipeName, VSCODE_HANDLES_UNCAUGHT_ERRORS: true, - ELECTRON_NO_ASAR: '1', VSCODE_LOG_STACK: !this._isExtensionDevTestFromCli && (this._isExtensionDevHost || !this._environmentService.isBuilt || product.quality !== 'stable' || this._environmentService.verbose) }), // We only detach the extension host on windows. Linux and Mac orphan by default diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index 9b73f7739ecfa..acaccc6693aa1 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -13,11 +13,14 @@ import { normalizeNFD, startsWith } from 'vs/base/common/strings'; import { IFolderSearch, IRawSearch } from './search'; import { foldersToIncludeGlobs, foldersToRgExcludeGlobs } from './ripgrepTextSearch'; +// If vscode-ripgrep is in an .asar file, then the binary is unpacked. +const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.unpacked'); + export function spawnRipgrepCmd(config: IRawSearch, folderQuery: IFolderSearch, includePattern: glob.IExpression, excludePattern: glob.IExpression) { const rgArgs = getRgArgs(config, folderQuery, includePattern, excludePattern); const cwd = folderQuery.folder; return { - cmd: cp.spawn(rgPath, rgArgs.args, { cwd }), + cmd: cp.spawn(rgDiskPath, rgArgs.args, { cwd }), siblingClauses: rgArgs.siblingClauses, rgArgs, cwd diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts index 72ecb4b919d37..cbc4bd814a69b 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts @@ -23,6 +23,9 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, IFolderSearch, LineMatch, FileMatch } from './search'; import { IProgress } from 'vs/platform/search/common/search'; +// If vscode-ripgrep is in an .asar file, then the binary is unpacked. +const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.unpacked'); + export class RipgrepEngine { private isDone = false; private rgProc: cp.ChildProcess; @@ -72,7 +75,7 @@ export class RipgrepEngine { onMessage({ message: rgCmd }); }); - this.rgProc = cp.spawn(rgPath, rgArgs.args, { cwd }); + this.rgProc = cp.spawn(rgDiskPath, rgArgs.args, { cwd }); process.once('exit', this.killRgProcFn); this.ripgrepParser = new RipgrepParser(this.config.maxResults, cwd, this.config.extraFiles); diff --git a/yarn.lock b/yarn.lock index babc32c79839f..1212dc17880c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -228,6 +228,19 @@ asap@~2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" +asar@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/asar/-/asar-0.14.0.tgz#998b36a26abd0e590e55d9f92cfd3fd7a6051652" + dependencies: + chromium-pickle-js "^0.2.0" + commander "^2.9.0" + cuint "^0.2.1" + glob "^6.0.4" + minimatch "^3.0.3" + mkdirp "^0.5.0" + mksnapshot "^0.3.0" + tmp "0.0.28" + asn1@0.1.11: version "0.1.11" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.1.11.tgz#559be18376d08a4ec4dbe80877d27818639b2df7" @@ -383,6 +396,13 @@ binary-search-bounds@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/binary-search-bounds/-/binary-search-bounds-2.0.3.tgz#5ff8616d6dd2ca5388bc85b2d6266e2b9da502dc" +binary@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" + dependencies: + buffers "~0.1.1" + chainsaw "~0.1.0" + binaryextensions@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-1.0.1.tgz#1e637488b35b58bda5f4774bf96a5212a8c90755" @@ -478,6 +498,10 @@ buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" +buffers@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" + bufferstreams@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/bufferstreams/-/bufferstreams-1.1.1.tgz#0161373060ac5988eff99058731114f6e195d51e" @@ -549,6 +573,12 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" +chainsaw@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" + dependencies: + traverse ">=0.3.0 <0.4" + chalk@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" @@ -595,6 +625,10 @@ chrome-remote-interface@^0.25.3: commander "2.11.x" ws "3.3.x" +chromium-pickle-js@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" + ci-info@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.1.tgz#47b44df118c48d2597b56d342e7e25791060171a" @@ -960,6 +994,10 @@ ctype@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" +cuint@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -1021,6 +1059,18 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" +decompress-zip@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/decompress-zip/-/decompress-zip-0.3.0.tgz#ae3bcb7e34c65879adfe77e19c30f86602b4bdb0" + dependencies: + binary "^0.3.0" + graceful-fs "^4.1.3" + mkpath "^0.1.0" + nopt "^3.0.1" + q "^1.1.2" + readable-stream "^1.1.8" + touch "0.0.3" + deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" @@ -1842,7 +1892,7 @@ fs-exists-sync@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" -fs-extra@^0.26.5: +fs-extra@0.26.7, fs-extra@^0.26.5: version "0.26.7" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.26.7.tgz#9ae1fdd94897798edab76d0918cf42d0c3184fa9" dependencies: @@ -2028,6 +2078,16 @@ glob@^4.3.1, glob@~4.5.x: minimatch "^2.0.1" once "^1.3.0" +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -2101,7 +2161,7 @@ gm@^1.14.2: cross-spawn "^4.0.0" debug "~2.2.0" -graceful-fs@4.1.11, graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@4.1.11, graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -3721,6 +3781,18 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@ dependencies: minimist "0.0.8" +mkpath@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/mkpath/-/mkpath-0.1.0.tgz#7554a6f8d871834cc97b5462b122c4c124d6de91" + +mksnapshot@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/mksnapshot/-/mksnapshot-0.3.1.tgz#2501c05657436d742ce958a4ff92c77e40dd37e6" + dependencies: + decompress-zip "0.3.0" + fs-extra "0.26.7" + request "^2.79.0" + mocha@^2.0.1, mocha@^2.2.5: version "2.5.3" resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" @@ -3833,7 +3905,7 @@ nodegit-promise@~4.0.0: dependencies: asap "~2.0.3" -nopt@3.x, nopt@~3.0.1: +nopt@3.x, nopt@^3.0.1, nopt@~3.0.1: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" dependencies: @@ -4643,6 +4715,15 @@ read@^1.0.7: isarray "0.0.1" string_decoder "~0.10.x" +readable-stream@^1.1.8, readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" @@ -4655,15 +4736,6 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readable-stream@~2.0.0, readable-stream@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -4801,7 +4873,7 @@ request@2.79.0, request@~2.79.0: tunnel-agent "~0.4.1" uuid "^3.0.0" -"request@>= 2.44.0 < 3.0.0", request@^2.45.0: +"request@>= 2.44.0 < 3.0.0", request@^2.45.0, request@^2.79.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: @@ -5451,6 +5523,12 @@ time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" +tmp@0.0.28: + version "0.0.28" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.28.tgz#172735b7f614ea7af39664fa84cf0de4e515d120" + dependencies: + os-tmpdir "~1.0.1" + tmp@0.0.29: version "0.0.29" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" @@ -5467,12 +5545,22 @@ to-iso-string@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" +touch@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/touch/-/touch-0.0.3.tgz#51aef3d449571d4f287a5d87c9c8b49181a0db1d" + dependencies: + nopt "~1.0.10" + tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" dependencies: punycode "^1.4.1" +"traverse@>=0.3.0 <0.4": + version "0.3.9" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"