@dependabot/yarn-lib
Version:
📦🐈 Fast, reliable, and secure dependency management.
546 lines (445 loc) • 16.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _asyncToGenerator2;
function _load_asyncToGenerator() {
return _asyncToGenerator2 = _interopRequireDefault(require('babel-runtime/helpers/asyncToGenerator'));
}
var _config;
function _load_config() {
return _config = _interopRequireDefault(require('./config.js'));
}
var _executeLifecycleScript;
function _load_executeLifecycleScript() {
return _executeLifecycleScript = _interopRequireDefault(require('./util/execute-lifecycle-script.js'));
}
var _crypto;
function _load_crypto() {
return _crypto = _interopRequireWildcard(require('./util/crypto.js'));
}
var _fs;
function _load_fs() {
return _fs = _interopRequireWildcard(require('./util/fs.js'));
}
var _packageNameUtils;
function _load_packageNameUtils() {
return _packageNameUtils = require('./util/package-name-utils.js');
}
var _pack;
function _load_pack() {
return _pack = require('./cli/commands/pack.js');
}
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const fs = require('fs');
const invariant = require('invariant');
const path = require('path');
const INSTALL_STAGES = ['preinstall', 'install', 'postinstall'];
class PackageInstallScripts {
constructor(config, resolver, force) {
this.installed = 0;
this.resolver = resolver;
this.reporter = config.reporter;
this.config = config;
this.force = force;
this.artifacts = {};
}
setForce(force) {
this.force = force;
}
setArtifacts(artifacts) {
this.artifacts = artifacts;
}
getArtifacts() {
return this.artifacts;
}
getInstallCommands(pkg) {
const scripts = pkg.scripts;
if (scripts) {
const cmds = [];
for (var _iterator = INSTALL_STAGES, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
const stage = _ref;
const cmd = scripts[stage];
if (cmd) {
cmds.push([stage, cmd]);
}
}
return cmds;
} else {
return [];
}
}
walk(loc) {
var _this = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
const files = yield (_fs || _load_fs()).walk(loc, null, new Set(_this.config.registryFolders));
const mtimes = new Map();
for (var _iterator2 = files, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
const file = _ref2;
mtimes.set(file.relative, file.mtime);
}
return mtimes;
})();
}
saveBuildArtifacts(loc, pkg, beforeFiles, spinner) {
var _this2 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
const afterFiles = yield _this2.walk(loc);
// work out what files have been created/modified
const buildArtifacts = [];
for (var _iterator3 = afterFiles, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref4;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref4 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref4 = _i3.value;
}
const _ref3 = _ref4;
const file = _ref3[0];
const mtime = _ref3[1];
if (!beforeFiles.has(file) || beforeFiles.get(file) !== mtime) {
buildArtifacts.push(file);
}
}
if (!buildArtifacts.length) {
// nothing else to do here since we have no build artifacts
return;
}
// set build artifacts
const ref = pkg._reference;
invariant(ref, 'expected reference');
_this2.artifacts[`${pkg.name}@${pkg.version}`] = buildArtifacts;
})();
}
install(cmds, pkg, spinner) {
var _this3 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
const ref = pkg._reference;
invariant(ref, 'expected reference');
const loc = _this3.config.generateHardModulePath(ref);
try {
for (var _iterator4 = cmds, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
var _ref6;
if (_isArray4) {
if (_i4 >= _iterator4.length) break;
_ref6 = _iterator4[_i4++];
} else {
_i4 = _iterator4.next();
if (_i4.done) break;
_ref6 = _i4.value;
}
const _ref5 = _ref6;
const stage = _ref5[0];
const cmd = _ref5[1];
var _ref7 = yield (0, (_executeLifecycleScript || _load_executeLifecycleScript()).default)(stage, _this3.config, loc, cmd, spinner);
const stdout = _ref7.stdout;
_this3.reporter.verbose(stdout);
}
} catch (err) {
err.message = `${loc}: ${err.message}`;
invariant(ref, 'expected reference');
if (ref.optional) {
ref.ignore = true;
ref.incompatible = true;
_this3.reporter.warn(_this3.reporter.lang('optionalModuleScriptFail', err.message));
_this3.reporter.info(_this3.reporter.lang('optionalModuleFail'));
// Cleanup node_modules
try {
yield (_fs || _load_fs()).unlink(loc);
} catch (e) {
_this3.reporter.error(_this3.reporter.lang('optionalModuleCleanupFail', e.message));
}
} else {
throw err;
}
}
})();
}
packageCanBeInstalled(pkg) {
const cmds = this.getInstallCommands(pkg);
if (!cmds.length) {
return false;
}
if (this.config.packBuiltPackages && pkg.prebuiltVariants) {
for (const variant in pkg.prebuiltVariants) {
if (pkg._remote && pkg._remote.reference && pkg._remote.reference.includes(variant)) {
return false;
}
}
}
const ref = pkg._reference;
invariant(ref, 'Missing package reference');
if (!ref.fresh && !this.force) {
// this package hasn't been touched
return false;
}
// Don't run lifecycle scripts for hoisted packages
if (!ref.location) {
return false;
}
// we haven't actually written this module out
if (ref.ignore) {
return false;
}
return true;
}
runCommand(spinner, pkg) {
var _this4 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
const cmds = _this4.getInstallCommands(pkg);
spinner.setPrefix(++_this4.installed, pkg.name);
yield _this4.install(cmds, pkg, spinner);
})();
}
// detect if there is a circularDependency in the dependency tree
detectCircularDependencies(root, seenManifests, pkg) {
const ref = pkg._reference;
invariant(ref, 'expected reference');
const deps = ref.dependencies;
for (var _iterator5 = deps, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
var _ref8;
if (_isArray5) {
if (_i5 >= _iterator5.length) break;
_ref8 = _iterator5[_i5++];
} else {
_i5 = _iterator5.next();
if (_i5.done) break;
_ref8 = _i5.value;
}
const dep = _ref8;
const pkgDep = this.resolver.getStrictResolvedPattern(dep);
if (seenManifests.has(pkgDep)) {
// there is a cycle but not with the root
continue;
}
seenManifests.add(pkgDep);
// found a dependency pointing to root
if (pkgDep == root) {
return true;
}
if (this.detectCircularDependencies(root, seenManifests, pkgDep)) {
return true;
}
}
return false;
}
// find the next package to be installed
findInstallablePackage(workQueue, installed) {
for (var _iterator6 = workQueue, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
var _ref9;
if (_isArray6) {
if (_i6 >= _iterator6.length) break;
_ref9 = _iterator6[_i6++];
} else {
_i6 = _iterator6.next();
if (_i6.done) break;
_ref9 = _i6.value;
}
const pkg = _ref9;
const ref = pkg._reference;
invariant(ref, 'expected reference');
const deps = ref.dependencies;
let dependenciesFullfilled = true;
for (var _iterator7 = deps, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
var _ref10;
if (_isArray7) {
if (_i7 >= _iterator7.length) break;
_ref10 = _iterator7[_i7++];
} else {
_i7 = _iterator7.next();
if (_i7.done) break;
_ref10 = _i7.value;
}
const dep = _ref10;
const pkgDep = this.resolver.getStrictResolvedPattern(dep);
if (!installed.has(pkgDep)) {
dependenciesFullfilled = false;
break;
}
}
// all depedencies are installed
if (dependenciesFullfilled) {
return pkg;
}
// detect circular dependency, mark this pkg as installable to break the circle
if (this.detectCircularDependencies(pkg, new Set(), pkg)) {
return pkg;
}
}
return null;
}
worker(spinner, workQueue, installed, waitQueue) {
var _this5 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
while (true) {
// No more work to be done
if (workQueue.size == 0) {
break;
}
// find a installable package
const pkg = _this5.findInstallablePackage(workQueue, installed);
// can't find a package to install, register into waitQueue
if (pkg == null) {
spinner.clear();
yield new Promise(function (resolve) {
return waitQueue.add(resolve);
});
continue;
}
// found a package to install
workQueue.delete(pkg);
if (_this5.packageCanBeInstalled(pkg)) {
yield _this5.runCommand(spinner, pkg);
}
installed.add(pkg);
for (var _iterator8 = waitQueue, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
var _ref11;
if (_isArray8) {
if (_i8 >= _iterator8.length) break;
_ref11 = _iterator8[_i8++];
} else {
_i8 = _iterator8.next();
if (_i8.done) break;
_ref11 = _i8.value;
}
const workerResolve = _ref11;
workerResolve();
}
waitQueue.clear();
}
})();
}
init(seedPatterns) {
var _this6 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
const workQueue = new Set();
const installed = new Set();
const pkgs = _this6.resolver.getTopologicalManifests(seedPatterns);
let installablePkgs = 0;
// A map to keep track of what files exist before installation
const beforeFilesMap = new Map();
for (var _iterator9 = pkgs, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
var _ref12;
if (_isArray9) {
if (_i9 >= _iterator9.length) break;
_ref12 = _iterator9[_i9++];
} else {
_i9 = _iterator9.next();
if (_i9.done) break;
_ref12 = _i9.value;
}
const pkg = _ref12;
if (_this6.packageCanBeInstalled(pkg)) {
const ref = pkg._reference;
invariant(ref, 'expected reference');
const loc = _this6.config.generateHardModulePath(ref);
beforeFilesMap.set(loc, (yield _this6.walk(loc)));
installablePkgs += 1;
}
workQueue.add(pkg);
}
// waitQueue acts like a semaphore to allow workers to register to be notified
// when there are more work added to the work queue
const waitQueue = new Set();
const workers = [];
const set = _this6.reporter.activitySet(installablePkgs, Math.min(_this6.config.childConcurrency, workQueue.size));
for (var _iterator10 = set.spinners, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
var _ref13;
if (_isArray10) {
if (_i10 >= _iterator10.length) break;
_ref13 = _iterator10[_i10++];
} else {
_i10 = _iterator10.next();
if (_i10.done) break;
_ref13 = _i10.value;
}
const spinner = _ref13;
workers.push(_this6.worker(spinner, workQueue, installed, waitQueue));
}
yield Promise.all(workers);
// generate built package as prebuilt one for offline mirror
const offlineMirrorPath = _this6.config.getOfflineMirrorPath();
if (_this6.config.packBuiltPackages && offlineMirrorPath) {
for (var _iterator11 = pkgs, _isArray11 = Array.isArray(_iterator11), _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {
var _ref14;
if (_isArray11) {
if (_i11 >= _iterator11.length) break;
_ref14 = _iterator11[_i11++];
} else {
_i11 = _iterator11.next();
if (_i11.done) break;
_ref14 = _i11.value;
}
const pkg = _ref14;
if (_this6.packageCanBeInstalled(pkg)) {
let prebuiltPath = path.join(offlineMirrorPath, 'prebuilt');
yield (_fs || _load_fs()).mkdirp(prebuiltPath);
const prebuiltFilename = (0, (_packageNameUtils || _load_packageNameUtils()).getPlatformSpecificPackageFilename)(pkg);
prebuiltPath = path.join(prebuiltPath, prebuiltFilename + '.tgz');
const ref = pkg._reference;
invariant(ref, 'expected reference');
const builtPackagePath = _this6.config.generateHardModulePath(ref);
const pkgConfig = yield (_config || _load_config()).default.create({
cwd: builtPackagePath
}, _this6.reporter);
const stream = yield (0, (_pack || _load_pack()).pack)(pkgConfig, builtPackagePath);
const hash = yield new Promise(function (resolve, reject) {
const validateStream = new (_crypto || _load_crypto()).HashStream();
stream.pipe(validateStream).pipe(fs.createWriteStream(prebuiltPath)).on('error', reject).on('close', function () {
return resolve(validateStream.getHash());
});
});
pkg.prebuiltVariants = pkg.prebuiltVariants || {};
pkg.prebuiltVariants[prebuiltFilename] = hash;
}
}
} else {
// cache all build artifacts
for (var _iterator12 = pkgs, _isArray12 = Array.isArray(_iterator12), _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {
var _ref15;
if (_isArray12) {
if (_i12 >= _iterator12.length) break;
_ref15 = _iterator12[_i12++];
} else {
_i12 = _iterator12.next();
if (_i12.done) break;
_ref15 = _i12.value;
}
const pkg = _ref15;
if (_this6.packageCanBeInstalled(pkg)) {
const ref = pkg._reference;
invariant(ref, 'expected reference');
const loc = _this6.config.generateHardModulePath(ref);
const beforeFiles = beforeFilesMap.get(loc);
invariant(beforeFiles, 'files before installation should always be recorded');
yield _this6.saveBuildArtifacts(loc, pkg, beforeFiles, set.spinners[0]);
}
}
}
set.end();
})();
}
}
exports.default = PackageInstallScripts;