UNPKG

39.4 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.linkBin = undefined;
7
8var _asyncToGenerator2;
9
10function _load_asyncToGenerator() {
11 return _asyncToGenerator2 = _interopRequireDefault(require('babel-runtime/helpers/asyncToGenerator'));
12}
13
14let linkBin = exports.linkBin = (() => {
15 var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (src, dest) {
16 if (process.platform === 'win32') {
17 const unlockMutex = yield (0, (_mutex || _load_mutex()).default)(src);
18 try {
19 yield cmdShim(src, dest);
20 } finally {
21 unlockMutex();
22 }
23 } else {
24 yield (_fs || _load_fs()).mkdirp(path.dirname(dest));
25 yield (_fs || _load_fs()).symlink(src, dest);
26 yield (_fs || _load_fs()).chmod(dest, '755');
27 }
28 });
29
30 return function linkBin(_x, _x2) {
31 return _ref.apply(this, arguments);
32 };
33})();
34
35var _packageHoister;
36
37function _load_packageHoister() {
38 return _packageHoister = _interopRequireDefault(require('./package-hoister.js'));
39}
40
41var _constants;
42
43function _load_constants() {
44 return _constants = _interopRequireWildcard(require('./constants.js'));
45}
46
47var _promise;
48
49function _load_promise() {
50 return _promise = _interopRequireWildcard(require('./util/promise.js'));
51}
52
53var _normalizePattern2;
54
55function _load_normalizePattern() {
56 return _normalizePattern2 = require('./util/normalize-pattern.js');
57}
58
59var _misc;
60
61function _load_misc() {
62 return _misc = require('./util/misc.js');
63}
64
65var _fs;
66
67function _load_fs() {
68 return _fs = _interopRequireWildcard(require('./util/fs.js'));
69}
70
71var _mutex;
72
73function _load_mutex() {
74 return _mutex = _interopRequireDefault(require('./util/mutex.js'));
75}
76
77var _semver;
78
79function _load_semver() {
80 return _semver = require('./util/semver.js');
81}
82
83var _workspaceLayout;
84
85function _load_workspaceLayout() {
86 return _workspaceLayout = _interopRequireDefault(require('./workspace-layout.js'));
87}
88
89function _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; } }
90
91function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
92
93const invariant = require('invariant');
94
95const cmdShim = require('@zkochan/cmd-shim');
96const path = require('path');
97const semver = require('semver');
98// Concurrency for creating bin links disabled because of the issue #1961
99const linkBinConcurrency = 1;
100
101class PackageLinker {
102 constructor(config, resolver) {
103 this.resolver = resolver;
104 this.reporter = config.reporter;
105 this.config = config;
106 this.artifacts = {};
107 this.topLevelBinLinking = true;
108 this.unplugged = [];
109 }
110
111 setArtifacts(artifacts) {
112 this.artifacts = artifacts;
113 }
114
115 setTopLevelBinLinking(topLevelBinLinking) {
116 this.topLevelBinLinking = topLevelBinLinking;
117 }
118
119 linkSelfDependencies(pkg, pkgLoc, targetBinLoc, override = false) {
120 return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
121 targetBinLoc = path.join(targetBinLoc, '.bin');
122 yield (_fs || _load_fs()).mkdirp(targetBinLoc);
123 targetBinLoc = yield (_fs || _load_fs()).realpath(targetBinLoc);
124 pkgLoc = yield (_fs || _load_fs()).realpath(pkgLoc);
125 for (var _iterator = (0, (_misc || _load_misc()).entries)(pkg.bin), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
126 var _ref3;
127
128 if (_isArray) {
129 if (_i >= _iterator.length) break;
130 _ref3 = _iterator[_i++];
131 } else {
132 _i = _iterator.next();
133 if (_i.done) break;
134 _ref3 = _i.value;
135 }
136
137 const _ref2 = _ref3;
138 const scriptName = _ref2[0];
139 const scriptCmd = _ref2[1];
140
141 const dest = path.join(targetBinLoc, scriptName);
142 const src = path.join(pkgLoc, scriptCmd);
143 if (!(yield (_fs || _load_fs()).exists(src))) {
144 if (!override) {
145 // TODO maybe throw an error
146 continue;
147 }
148 }
149 yield linkBin(src, dest);
150 }
151 })();
152 }
153
154 linkBinDependencies(pkg, dir) {
155 var _this = this;
156
157 return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
158 const deps = [];
159
160 const ref = pkg._reference;
161 invariant(ref, 'Package reference is missing');
162
163 const remote = pkg._remote;
164 invariant(remote, 'Package remote is missing');
165
166 // link up `bin scripts` in `dependencies`
167 for (var _iterator2 = ref.dependencies, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
168 var _ref4;
169
170 if (_isArray2) {
171 if (_i2 >= _iterator2.length) break;
172 _ref4 = _iterator2[_i2++];
173 } else {
174 _i2 = _iterator2.next();
175 if (_i2.done) break;
176 _ref4 = _i2.value;
177 }
178
179 const pattern = _ref4;
180
181 const dep = _this.resolver.getStrictResolvedPattern(pattern);
182 if (
183 // Missing locations means not installed inside node_modules
184 dep._reference && dep._reference.locations.length && dep.bin && Object.keys(dep.bin).length) {
185 const loc = yield _this.findNearestInstalledVersionOfPackage(dep, dir);
186 deps.push({ dep, loc });
187 }
188 }
189
190 // link up the `bin` scripts in bundled dependencies
191 if (pkg.bundleDependencies) {
192 for (var _iterator3 = pkg.bundleDependencies, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
193 var _ref5;
194
195 if (_isArray3) {
196 if (_i3 >= _iterator3.length) break;
197 _ref5 = _iterator3[_i3++];
198 } else {
199 _i3 = _iterator3.next();
200 if (_i3.done) break;
201 _ref5 = _i3.value;
202 }
203
204 const depName = _ref5;
205
206 const locs = ref.locations.map(function (loc) {
207 return path.join(loc, _this.config.getFolder(pkg), depName);
208 });
209 try {
210 const dep = yield _this.config.readManifest(locs[0], remote.registry); //all of them should be the same
211
212 if (dep.bin && Object.keys(dep.bin).length) {
213 deps.push(...locs.map(function (loc) {
214 return { dep, loc };
215 }));
216 }
217 } catch (ex) {
218 if (ex.code !== 'ENOENT') {
219 throw ex;
220 }
221 // intentionally ignoring ENOENT error.
222 // bundledDependency either does not exist or does not contain a package.json
223 }
224 }
225 }
226
227 // no deps to link
228 if (!deps.length) {
229 return;
230 }
231
232 // write the executables
233 for (var _iterator4 = deps, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
234 var _ref7;
235
236 if (_isArray4) {
237 if (_i4 >= _iterator4.length) break;
238 _ref7 = _iterator4[_i4++];
239 } else {
240 _i4 = _iterator4.next();
241 if (_i4.done) break;
242 _ref7 = _i4.value;
243 }
244
245 const _ref6 = _ref7;
246 const dep = _ref6.dep,
247 loc = _ref6.loc;
248
249 if (dep._reference && dep._reference.locations.length) {
250 invariant(!dep._reference.isPlugnplay, "Plug'n'play packages should not be referenced here");
251 yield _this.linkSelfDependencies(dep, loc, dir);
252 }
253 }
254 })();
255 }
256
257 //find the installation location of ref that would be used in binLoc based on node module resolution
258 findNearestInstalledVersionOfPackage(pkg, binLoc) {
259 var _this2 = this;
260
261 return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
262 const ref = pkg._reference;
263 invariant(ref, 'expected pkg reference for ' + pkg.name);
264 const moduleFolder = _this2.config.getFolder(pkg);
265 yield (_fs || _load_fs()).mkdirp(binLoc);
266 const realBinLoc = yield (_fs || _load_fs()).realpath(binLoc);
267
268 const allLocations = [...ref.locations];
269 const realLocations = yield Promise.all(ref.locations.map(function (loc) {
270 return (_fs || _load_fs()).realpath(loc);
271 }));
272 realLocations.forEach(function (loc) {
273 return allLocations.indexOf(loc) !== -1 || allLocations.push(loc);
274 });
275
276 const locationBinLocPairs = allLocations.map(function (loc) {
277 return [loc, binLoc];
278 });
279 if (binLoc !== realBinLoc) {
280 locationBinLocPairs.push(...allLocations.map(function (loc) {
281 return [loc, realBinLoc];
282 }));
283 }
284
285 const distancePairs = locationBinLocPairs.map(function ([loc, curBinLoc]) {
286 let distance = 0;
287 let curLoc = curBinLoc;
288 let notFound = false;
289
290 while (path.join(curLoc, ref.name) !== loc && path.join(curLoc, moduleFolder, ref.name) !== loc) {
291 const next = path.dirname(curLoc);
292 if (curLoc === next) {
293 notFound = true;
294 break;
295 }
296
297 distance++;
298 curLoc = next;
299 }
300 return notFound ? null : [loc, distance];
301 });
302
303 //remove items where path was not found
304 const filteredDistancePairs = distancePairs.filter(function (d) {
305 return d;
306 });
307 filteredDistancePairs;
308
309 invariant(filteredDistancePairs.length > 0, `could not find a copy of ${pkg.name} to link in ${binLoc}`);
310
311 //get smallest distance from package location
312 const minItem = filteredDistancePairs.reduce(function (min, cur) {
313 return cur[1] < min[1] ? cur : min;
314 });
315
316 invariant(minItem[1] >= 0, 'could not find a target for bin dir of ' + minItem.toString());
317 return minItem[0];
318 })();
319 }
320
321 getFlatHoistedTree(patterns, workspaceLayout, { ignoreOptional } = {}) {
322 const hoister = new (_packageHoister || _load_packageHoister()).default(this.config, this.resolver, { ignoreOptional, workspaceLayout });
323 hoister.seed(patterns);
324 if (this.config.focus) {
325 hoister.markShallowWorkspaceEntries();
326 }
327 return hoister.init();
328 }
329
330 copyModules(patterns, workspaceLayout, { linkDuplicates, ignoreOptional } = {}) {
331 var _this3 = this;
332
333 return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
334 let flatTree = _this3.getFlatHoistedTree(patterns, workspaceLayout, { ignoreOptional });
335 // sorted tree makes file creation and copying not to interfere with each other
336 flatTree = flatTree.sort(function (dep1, dep2) {
337 return dep1[0].localeCompare(dep2[0]);
338 });
339
340 // list of artifacts in modules to remove from extraneous removal
341 const artifactFiles = [];
342
343 const copyQueue = new Map();
344 const hardlinkQueue = new Map();
345 const hardlinksEnabled = linkDuplicates && (yield (_fs || _load_fs()).hardlinksWork(_this3.config.cwd));
346
347 const copiedSrcs = new Map();
348 const symlinkPaths = new Map();
349 for (var _iterator5 = flatTree, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
350 var _ref9;
351
352 if (_isArray5) {
353 if (_i5 >= _iterator5.length) break;
354 _ref9 = _iterator5[_i5++];
355 } else {
356 _i5 = _iterator5.next();
357 if (_i5.done) break;
358 _ref9 = _i5.value;
359 }
360
361 const _ref8 = _ref9;
362 const folder = _ref8[0];
363 var _ref8$ = _ref8[1];
364 const pkg = _ref8$.pkg;
365 const loc = _ref8$.loc;
366 const isShallow = _ref8$.isShallow;
367
368 const remote = pkg._remote || { type: '' };
369 const ref = pkg._reference;
370 let dest = folder;
371 invariant(ref, 'expected package reference');
372
373 let src = loc;
374 let type = '';
375 if (remote.type === 'link') {
376 // replace package source from incorrect cache location (workspaces and link: are not cached)
377 // with a symlink source
378 src = remote.reference;
379 type = 'symlink';
380 } else if (workspaceLayout && remote.type === 'workspace' && !isShallow) {
381 src = remote.reference;
382 type = 'symlink';
383 if (dest.indexOf(workspaceLayout.virtualManifestName) !== -1) {
384 // we don't need to install virtual manifest
385 continue;
386 }
387 // to get real path for non hoisted dependencies
388 symlinkPaths.set(dest, src);
389 } else {
390 // backwards compatibility: get build artifacts from metadata
391 // does not apply to symlinked dependencies
392 const metadata = yield _this3.config.readPackageMetadata(src);
393 for (var _iterator15 = metadata.artifacts, _isArray15 = Array.isArray(_iterator15), _i15 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {
394 var _ref23;
395
396 if (_isArray15) {
397 if (_i15 >= _iterator15.length) break;
398 _ref23 = _iterator15[_i15++];
399 } else {
400 _i15 = _iterator15.next();
401 if (_i15.done) break;
402 _ref23 = _i15.value;
403 }
404
405 const file = _ref23;
406
407 artifactFiles.push(path.join(dest, file));
408 }
409 }
410
411 for (var _iterator16 = symlinkPaths.entries(), _isArray16 = Array.isArray(_iterator16), _i16 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {
412 var _ref25;
413
414 if (_isArray16) {
415 if (_i16 >= _iterator16.length) break;
416 _ref25 = _iterator16[_i16++];
417 } else {
418 _i16 = _iterator16.next();
419 if (_i16.done) break;
420 _ref25 = _i16.value;
421 }
422
423 const _ref24 = _ref25;
424 const symlink = _ref24[0];
425 const realpath = _ref24[1];
426
427 if (dest.indexOf(symlink + path.sep) === 0) {
428 // after hoisting we end up with this structure
429 // root/node_modules/workspace-package(symlink)/node_modules/package-a
430 // fs.copy operations can't copy files through a symlink, so all the paths under workspace-package
431 // need to be replaced with a real path, except for the symlink root/node_modules/workspace-package
432 dest = dest.replace(symlink, realpath);
433 }
434 }
435
436 if (_this3.config.plugnplayEnabled) {
437 ref.isPlugnplay = true;
438 if (yield _this3._isUnplugged(pkg, ref)) {
439 dest = _this3.config.generatePackageUnpluggedPath(ref);
440
441 // We don't skip the copy if the unplugged package isn't materialized yet
442 if (yield (_fs || _load_fs()).exists(dest)) {
443 ref.addLocation(dest);
444 continue;
445 }
446 } else {
447 ref.addLocation(src);
448 continue;
449 }
450 }
451
452 ref.addLocation(dest);
453
454 const integrityArtifacts = _this3.artifacts[`${pkg.name}@${pkg.version}`];
455 if (integrityArtifacts) {
456 for (var _iterator17 = integrityArtifacts, _isArray17 = Array.isArray(_iterator17), _i17 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {
457 var _ref26;
458
459 if (_isArray17) {
460 if (_i17 >= _iterator17.length) break;
461 _ref26 = _iterator17[_i17++];
462 } else {
463 _i17 = _iterator17.next();
464 if (_i17.done) break;
465 _ref26 = _i17.value;
466 }
467
468 const file = _ref26;
469
470 artifactFiles.push(path.join(dest, file));
471 }
472 }
473
474 const copiedDest = copiedSrcs.get(src);
475 if (!copiedDest) {
476 // no point to hardlink to a symlink
477 if (hardlinksEnabled && type !== 'symlink') {
478 copiedSrcs.set(src, dest);
479 }
480 copyQueue.set(dest, {
481 src,
482 dest,
483 type,
484 onFresh() {
485 if (ref) {
486 ref.setFresh(true);
487 }
488 }
489 });
490 } else {
491 hardlinkQueue.set(dest, {
492 src: copiedDest,
493 dest,
494 onFresh() {
495 if (ref) {
496 ref.setFresh(true);
497 }
498 }
499 });
500 }
501 }
502
503 const possibleExtraneous = new Set();
504 const scopedPaths = new Set();
505
506 const findExtraneousFiles = (() => {
507 var _ref10 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (basePath) {
508 for (var _iterator6 = _this3.config.registryFolders, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
509 var _ref11;
510
511 if (_isArray6) {
512 if (_i6 >= _iterator6.length) break;
513 _ref11 = _iterator6[_i6++];
514 } else {
515 _i6 = _iterator6.next();
516 if (_i6.done) break;
517 _ref11 = _i6.value;
518 }
519
520 const folder = _ref11;
521
522 const loc = path.resolve(basePath, folder);
523
524 if (yield (_fs || _load_fs()).exists(loc)) {
525 const files = yield (_fs || _load_fs()).readdir(loc);
526
527 for (var _iterator7 = files, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
528 var _ref12;
529
530 if (_isArray7) {
531 if (_i7 >= _iterator7.length) break;
532 _ref12 = _iterator7[_i7++];
533 } else {
534 _i7 = _iterator7.next();
535 if (_i7.done) break;
536 _ref12 = _i7.value;
537 }
538
539 const file = _ref12;
540
541 const filepath = path.join(loc, file);
542
543 // it's a scope, not a package
544 if (file[0] === '@') {
545 scopedPaths.add(filepath);
546
547 for (var _iterator8 = yield (_fs || _load_fs()).readdir(filepath), _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
548 var _ref13;
549
550 if (_isArray8) {
551 if (_i8 >= _iterator8.length) break;
552 _ref13 = _iterator8[_i8++];
553 } else {
554 _i8 = _iterator8.next();
555 if (_i8.done) break;
556 _ref13 = _i8.value;
557 }
558
559 const subfile = _ref13;
560
561 possibleExtraneous.add(path.join(filepath, subfile));
562 }
563 } else {
564 possibleExtraneous.add(filepath);
565 }
566 }
567 }
568 }
569 });
570
571 return function findExtraneousFiles(_x3) {
572 return _ref10.apply(this, arguments);
573 };
574 })();
575
576 yield findExtraneousFiles(_this3.config.lockfileFolder);
577 if (workspaceLayout) {
578 for (var _iterator9 = Object.keys(workspaceLayout.workspaces), _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
579 var _ref14;
580
581 if (_isArray9) {
582 if (_i9 >= _iterator9.length) break;
583 _ref14 = _iterator9[_i9++];
584 } else {
585 _i9 = _iterator9.next();
586 if (_i9.done) break;
587 _ref14 = _i9.value;
588 }
589
590 const workspaceName = _ref14;
591
592 yield findExtraneousFiles(workspaceLayout.workspaces[workspaceName].loc);
593 }
594 }
595
596 // If an Extraneous is an entry created via "yarn link", we prevent it from being overwritten.
597 // Unfortunately, the only way we can know if they have been created this way is to check if they
598 // are symlinks - problem is that it then conflicts with the newly introduced "link:" protocol,
599 // which also creates symlinks :( a somewhat weak fix is to check if the symlink target is registered
600 // inside the linkFolder, in which case we assume it has been created via "yarn link". Otherwise, we
601 // assume it's a link:-managed dependency, and overwrite it as usual.
602 const linkTargets = new Map();
603
604 let linkedModules;
605 try {
606 linkedModules = yield (_fs || _load_fs()).readdir(_this3.config.linkFolder);
607 } catch (err) {
608 if (err.code === 'ENOENT') {
609 linkedModules = [];
610 } else {
611 throw err;
612 }
613 }
614
615 // TODO: Consolidate this logic with `this.config.linkedModules` logic
616 for (var _iterator10 = linkedModules, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
617 var _ref15;
618
619 if (_isArray10) {
620 if (_i10 >= _iterator10.length) break;
621 _ref15 = _iterator10[_i10++];
622 } else {
623 _i10 = _iterator10.next();
624 if (_i10.done) break;
625 _ref15 = _i10.value;
626 }
627
628 const entry = _ref15;
629
630 const entryPath = path.join(_this3.config.linkFolder, entry);
631 const stat = yield (_fs || _load_fs()).lstat(entryPath);
632
633 if (stat.isSymbolicLink()) {
634 try {
635 const entryTarget = yield (_fs || _load_fs()).realpath(entryPath);
636 linkTargets.set(entry, entryTarget);
637 } catch (err) {
638 _this3.reporter.warn(_this3.reporter.lang('linkTargetMissing', entry));
639 yield (_fs || _load_fs()).unlink(entryPath);
640 }
641 } else if (stat.isDirectory() && entry[0] === '@') {
642 // if the entry is directory beginning with '@', then we're dealing with a package scope, which
643 // means we must iterate inside to retrieve the package names it contains
644 const scopeName = entry;
645
646 for (var _iterator18 = yield (_fs || _load_fs()).readdir(entryPath), _isArray18 = Array.isArray(_iterator18), _i18 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {
647 var _ref27;
648
649 if (_isArray18) {
650 if (_i18 >= _iterator18.length) break;
651 _ref27 = _iterator18[_i18++];
652 } else {
653 _i18 = _iterator18.next();
654 if (_i18.done) break;
655 _ref27 = _i18.value;
656 }
657
658 const entry2 = _ref27;
659
660 const entryPath2 = path.join(entryPath, entry2);
661 const stat2 = yield (_fs || _load_fs()).lstat(entryPath2);
662
663 if (stat2.isSymbolicLink()) {
664 const packageName = `${scopeName}/${entry2}`;
665 try {
666 const entryTarget = yield (_fs || _load_fs()).realpath(entryPath2);
667 linkTargets.set(packageName, entryTarget);
668 } catch (err) {
669 _this3.reporter.warn(_this3.reporter.lang('linkTargetMissing', packageName));
670 yield (_fs || _load_fs()).unlink(entryPath2);
671 }
672 }
673 }
674 }
675 }
676
677 for (var _iterator11 = possibleExtraneous, _isArray11 = Array.isArray(_iterator11), _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {
678 var _ref16;
679
680 if (_isArray11) {
681 if (_i11 >= _iterator11.length) break;
682 _ref16 = _iterator11[_i11++];
683 } else {
684 _i11 = _iterator11.next();
685 if (_i11.done) break;
686 _ref16 = _i11.value;
687 }
688
689 const loc = _ref16;
690
691 let packageName = path.basename(loc);
692 const scopeName = path.basename(path.dirname(loc));
693
694 if (scopeName[0] === `@`) {
695 packageName = `${scopeName}/${packageName}`;
696 }
697
698 if ((yield (_fs || _load_fs()).lstat(loc)).isSymbolicLink() && linkTargets.has(packageName) && linkTargets.get(packageName) === (yield (_fs || _load_fs()).realpath(loc))) {
699 possibleExtraneous.delete(loc);
700 copyQueue.delete(loc);
701 }
702 }
703
704 //
705 let tick;
706 yield (_fs || _load_fs()).copyBulk(Array.from(copyQueue.values()), _this3.reporter, {
707 possibleExtraneous,
708 artifactFiles,
709
710 ignoreBasenames: [(_constants || _load_constants()).METADATA_FILENAME, (_constants || _load_constants()).TARBALL_FILENAME],
711
712 onStart: function onStart(num) {
713 tick = _this3.reporter.progress(num);
714 },
715
716 onProgress(src) {
717 if (tick) {
718 tick();
719 }
720 }
721 });
722
723 yield (_fs || _load_fs()).hardlinkBulk(Array.from(hardlinkQueue.values()), _this3.reporter, {
724 possibleExtraneous,
725 artifactFiles,
726
727 onStart: function onStart(num) {
728 tick = _this3.reporter.progress(num);
729 },
730
731 onProgress(src) {
732 if (tick) {
733 tick();
734 }
735 }
736 });
737
738 // remove all extraneous files that weren't in the tree
739 for (var _iterator12 = possibleExtraneous, _isArray12 = Array.isArray(_iterator12), _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {
740 var _ref17;
741
742 if (_isArray12) {
743 if (_i12 >= _iterator12.length) break;
744 _ref17 = _iterator12[_i12++];
745 } else {
746 _i12 = _iterator12.next();
747 if (_i12.done) break;
748 _ref17 = _i12.value;
749 }
750
751 const loc = _ref17;
752
753 _this3.reporter.verbose(_this3.reporter.lang('verboseFileRemoveExtraneous', loc));
754 yield (_fs || _load_fs()).unlink(loc);
755 }
756
757 // remove any empty scoped directories
758 for (var _iterator13 = scopedPaths, _isArray13 = Array.isArray(_iterator13), _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {
759 var _ref18;
760
761 if (_isArray13) {
762 if (_i13 >= _iterator13.length) break;
763 _ref18 = _iterator13[_i13++];
764 } else {
765 _i13 = _iterator13.next();
766 if (_i13.done) break;
767 _ref18 = _i13.value;
768 }
769
770 const scopedPath = _ref18;
771
772 const files = yield (_fs || _load_fs()).readdir(scopedPath);
773 if (files.length === 0) {
774 yield (_fs || _load_fs()).unlink(scopedPath);
775 }
776 }
777
778 // create binary links
779 if (_this3.config.getOption('bin-links') && _this3.config.binLinks !== false) {
780 const topLevelDependencies = _this3.determineTopLevelBinLinkOrder(flatTree);
781 const tickBin = _this3.reporter.progress(flatTree.length + topLevelDependencies.length);
782
783 // create links in transient dependencies
784 yield (_promise || _load_promise()).queue(flatTree, (() => {
785 var _ref19 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* ([dest, { pkg, isNohoist, parts }]) {
786 if (pkg._reference && pkg._reference.locations.length && !pkg._reference.isPlugnplay) {
787 const binLoc = path.join(dest, _this3.config.getFolder(pkg));
788 yield _this3.linkBinDependencies(pkg, binLoc);
789 if (isNohoist) {
790 // if nohoist, we need to override the binLink to point to the local destination
791 const parentBinLoc = _this3.getParentBinLoc(parts, flatTree);
792 yield _this3.linkSelfDependencies(pkg, dest, parentBinLoc, true);
793 }
794 tickBin();
795 }
796 tickBin();
797 });
798
799 return function (_x4) {
800 return _ref19.apply(this, arguments);
801 };
802 })(), linkBinConcurrency);
803
804 // create links at top level for all dependencies.
805 yield (_promise || _load_promise()).queue(topLevelDependencies, (() => {
806 var _ref20 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* ([dest, { pkg }]) {
807 if (pkg._reference && pkg._reference.locations.length && !pkg._reference.isPlugnplay && pkg.bin && Object.keys(pkg.bin).length) {
808 let binLoc;
809 if (_this3.config.modulesFolder) {
810 binLoc = path.join(_this3.config.modulesFolder);
811 } else {
812 binLoc = path.join(_this3.config.lockfileFolder, _this3.config.getFolder(pkg));
813 }
814 yield _this3.linkSelfDependencies(pkg, dest, binLoc);
815 }
816 tickBin();
817 });
818
819 return function (_x5) {
820 return _ref20.apply(this, arguments);
821 };
822 })(), linkBinConcurrency);
823 }
824
825 for (var _iterator14 = flatTree, _isArray14 = Array.isArray(_iterator14), _i14 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {
826 var _ref22;
827
828 if (_isArray14) {
829 if (_i14 >= _iterator14.length) break;
830 _ref22 = _iterator14[_i14++];
831 } else {
832 _i14 = _iterator14.next();
833 if (_i14.done) break;
834 _ref22 = _i14.value;
835 }
836
837 const _ref21 = _ref22;
838 const pkg = _ref21[1].pkg;
839
840 yield _this3._warnForMissingBundledDependencies(pkg);
841 }
842 })();
843 }
844
845 _buildTreeHash(flatTree) {
846 const hash = new Map();
847 for (var _iterator19 = flatTree, _isArray19 = Array.isArray(_iterator19), _i19 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {
848 var _ref29;
849
850 if (_isArray19) {
851 if (_i19 >= _iterator19.length) break;
852 _ref29 = _iterator19[_i19++];
853 } else {
854 _i19 = _iterator19.next();
855 if (_i19.done) break;
856 _ref29 = _i19.value;
857 }
858
859 const _ref28 = _ref29;
860 const dest = _ref28[0];
861 const hoistManifest = _ref28[1];
862
863 const key = hoistManifest.parts.join('#');
864 hash.set(key, [dest, hoistManifest]);
865 }
866 this._treeHash = hash;
867 return hash;
868 }
869
870 getParentBinLoc(parts, flatTree) {
871 const hash = this._treeHash || this._buildTreeHash(flatTree);
872 const parent = parts.slice(0, -1).join('#');
873 const tuple = hash.get(parent);
874 if (!tuple) {
875 throw new Error(`failed to get parent '${parent}' binLoc`);
876 }
877 const dest = tuple[0],
878 hoistManifest = tuple[1];
879
880 const parentBinLoc = path.join(dest, this.config.getFolder(hoistManifest.pkg));
881
882 return parentBinLoc;
883 }
884
885 determineTopLevelBinLinkOrder(flatTree) {
886 const linksToCreate = new Map();
887 for (var _iterator20 = flatTree, _isArray20 = Array.isArray(_iterator20), _i20 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {
888 var _ref31;
889
890 if (_isArray20) {
891 if (_i20 >= _iterator20.length) break;
892 _ref31 = _iterator20[_i20++];
893 } else {
894 _i20 = _iterator20.next();
895 if (_i20.done) break;
896 _ref31 = _i20.value;
897 }
898
899 const _ref30 = _ref31;
900 const dest = _ref30[0];
901 const hoistManifest = _ref30[1];
902 const pkg = hoistManifest.pkg,
903 isDirectRequire = hoistManifest.isDirectRequire,
904 isNohoist = hoistManifest.isNohoist,
905 isShallow = hoistManifest.isShallow;
906 const name = pkg.name;
907
908 // nohoist and shallow packages should not be linked at topLevel bin
909
910 if (!isNohoist && !isShallow && (isDirectRequire || this.topLevelBinLinking && !linksToCreate.has(name))) {
911 linksToCreate.set(name, [dest, hoistManifest]);
912 }
913 }
914
915 // Sort the array so that direct dependencies will be linked last.
916 // Bin links are overwritten if they already exist, so this will cause direct deps to take precedence.
917 // If someone finds this to be incorrect later, you could also consider sorting descending by
918 // `linkToCreate.level` which is the dependency tree depth. Direct deps will have level 0 and transitive
919 // deps will have level > 0.
920 const transientBins = [];
921 const topLevelBins = [];
922 for (var _iterator21 = Array.from(linksToCreate.values()), _isArray21 = Array.isArray(_iterator21), _i21 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {
923 var _ref32;
924
925 if (_isArray21) {
926 if (_i21 >= _iterator21.length) break;
927 _ref32 = _iterator21[_i21++];
928 } else {
929 _i21 = _iterator21.next();
930 if (_i21.done) break;
931 _ref32 = _i21.value;
932 }
933
934 const linkToCreate = _ref32;
935
936 if (linkToCreate[1].isDirectRequire) {
937 topLevelBins.push(linkToCreate);
938 } else {
939 transientBins.push(linkToCreate);
940 }
941 }
942 return [...transientBins, ...topLevelBins];
943 }
944
945 resolvePeerModules() {
946 for (var _iterator22 = this.resolver.getManifests(), _isArray22 = Array.isArray(_iterator22), _i22 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {
947 var _ref33;
948
949 if (_isArray22) {
950 if (_i22 >= _iterator22.length) break;
951 _ref33 = _iterator22[_i22++];
952 } else {
953 _i22 = _iterator22.next();
954 if (_i22.done) break;
955 _ref33 = _i22.value;
956 }
957
958 const pkg = _ref33;
959
960 const peerDeps = pkg.peerDependencies;
961 if (!peerDeps) {
962 continue;
963 }
964 const ref = pkg._reference;
965 invariant(ref, 'Package reference is missing');
966 // TODO: We are taking the "shortest" ref tree but there may be multiple ref trees with the same length
967 const refTree = ref.requests.map(req => req.parentNames).sort((arr1, arr2) => arr1.length - arr2.length)[0];
968
969 const getLevelDistance = pkgRef => {
970 let minDistance = Infinity;
971 for (var _iterator23 = pkgRef.requests, _isArray23 = Array.isArray(_iterator23), _i23 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {
972 var _ref34;
973
974 if (_isArray23) {
975 if (_i23 >= _iterator23.length) break;
976 _ref34 = _iterator23[_i23++];
977 } else {
978 _i23 = _iterator23.next();
979 if (_i23.done) break;
980 _ref34 = _i23.value;
981 }
982
983 const req = _ref34;
984
985 const distance = refTree.length - req.parentNames.length;
986
987 if (distance >= 0 && distance < minDistance && req.parentNames.every((name, idx) => name === refTree[idx])) {
988 minDistance = distance;
989 }
990 }
991
992 return minDistance;
993 };
994
995 for (const peerDepName in peerDeps) {
996 const range = peerDeps[peerDepName];
997 const peerPkgs = this.resolver.getAllInfoForPackageName(peerDepName);
998
999 let peerError = 'unmetPeer';
1000 let resolvedLevelDistance = Infinity;
1001 let resolvedPeerPkg;
1002 for (var _iterator24 = peerPkgs, _isArray24 = Array.isArray(_iterator24), _i24 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {
1003 var _ref35;
1004
1005 if (_isArray24) {
1006 if (_i24 >= _iterator24.length) break;
1007 _ref35 = _iterator24[_i24++];
1008 } else {
1009 _i24 = _iterator24.next();
1010 if (_i24.done) break;
1011 _ref35 = _i24.value;
1012 }
1013
1014 const peerPkg = _ref35;
1015
1016 const peerPkgRef = peerPkg._reference;
1017 if (!(peerPkgRef && peerPkgRef.patterns)) {
1018 continue;
1019 }
1020 const levelDistance = getLevelDistance(peerPkgRef);
1021 if (isFinite(levelDistance) && levelDistance < resolvedLevelDistance) {
1022 if (this._satisfiesPeerDependency(range, peerPkgRef.version)) {
1023 resolvedLevelDistance = levelDistance;
1024 resolvedPeerPkg = peerPkgRef;
1025 } else {
1026 peerError = 'incorrectPeer';
1027 }
1028 }
1029 }
1030
1031 if (resolvedPeerPkg) {
1032 ref.addDependencies(resolvedPeerPkg.patterns);
1033 this.reporter.verbose(this.reporter.lang('selectedPeer', `${pkg.name}@${pkg.version}`, `${peerDepName}@${resolvedPeerPkg.version}`, resolvedPeerPkg.level));
1034 } else {
1035 this.reporter.warn(this.reporter.lang(peerError, `${refTree.join(' > ')} > ${pkg.name}@${pkg.version}`, `${peerDepName}@${range}`));
1036 }
1037 }
1038 }
1039 }
1040
1041 _satisfiesPeerDependency(range, version) {
1042 return range === '*' || (0, (_semver || _load_semver()).satisfiesWithPrereleases)(version, range, this.config.looseSemver);
1043 }
1044
1045 _warnForMissingBundledDependencies(pkg) {
1046 var _this4 = this;
1047
1048 return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
1049 const ref = pkg._reference;
1050 invariant(ref, 'missing package ref ' + pkg.name);
1051
1052 if (pkg.bundleDependencies) {
1053 for (var _iterator25 = pkg.bundleDependencies, _isArray25 = Array.isArray(_iterator25), _i25 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {
1054 var _ref36;
1055
1056 if (_isArray25) {
1057 if (_i25 >= _iterator25.length) break;
1058 _ref36 = _iterator25[_i25++];
1059 } else {
1060 _i25 = _iterator25.next();
1061 if (_i25.done) break;
1062 _ref36 = _i25.value;
1063 }
1064
1065 const depName = _ref36;
1066
1067 const locs = ref.locations.map(function (loc) {
1068 return path.join(loc, _this4.config.getFolder(pkg), depName);
1069 });
1070 const locsExist = yield Promise.all(locs.map(function (loc) {
1071 return (_fs || _load_fs()).exists(loc);
1072 }));
1073 if (locsExist.some(function (e) {
1074 return !e;
1075 })) {
1076 //if any of the locs do not exist
1077 const pkgHuman = `${pkg.name}@${pkg.version}`;
1078 _this4.reporter.warn(_this4.reporter.lang('missingBundledDependency', pkgHuman, depName));
1079 }
1080 }
1081 }
1082 })();
1083 }
1084
1085 _isUnplugged(pkg, ref) {
1086 var _this5 = this;
1087
1088 return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
1089 // If an unplugged folder exists for the specified package, we simply use it
1090 if (yield (_fs || _load_fs()).exists(_this5.config.generatePackageUnpluggedPath(ref))) {
1091 return true;
1092 }
1093
1094 // If the package has a postinstall script, we also unplug it (otherwise they would run into the cache)
1095 if (pkg.scripts && (pkg.scripts.preinstall || pkg.scripts.install || pkg.scripts.postinstall)) {
1096 return true;
1097 }
1098
1099 // Check whether the user explicitly requested for the package to be unplugged
1100 return _this5.unplugged.some(function (patternToUnplug) {
1101 var _normalizePattern = (0, (_normalizePattern2 || _load_normalizePattern()).normalizePattern)(patternToUnplug);
1102
1103 const name = _normalizePattern.name,
1104 range = _normalizePattern.range,
1105 hasVersion = _normalizePattern.hasVersion;
1106
1107 const satisfiesSemver = hasVersion ? semver.satisfies(ref.version, range) : true;
1108 return name === ref.name && satisfiesSemver;
1109 });
1110 })();
1111 }
1112
1113 init(patterns, workspaceLayout, { linkDuplicates, ignoreOptional } = {}) {
1114 var _this6 = this;
1115
1116 return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
1117 _this6.resolvePeerModules();
1118 yield _this6.copyModules(patterns, workspaceLayout, { linkDuplicates, ignoreOptional });
1119
1120 if (!_this6.config.plugnplayEnabled) {
1121 yield (_fs || _load_fs()).unlink(`${_this6.config.lockfileFolder}/${(_constants || _load_constants()).PNP_FILENAME}`);
1122 }
1123 })();
1124 }
1125}
1126exports.default = PackageLinker;
\No newline at end of file