Skip to content

Commit

Permalink
testing a hardlinking strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
ef4 committed Sep 10, 2021
1 parent 5d2b89d commit 84cb4bb
Showing 1 changed file with 62 additions and 4 deletions.
66 changes: 62 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import fs = require('fs-extra');
import path = require('path');
import resolvePackagePath = require('resolve-package-path');
import { PackageJson } from 'type-fest';
import { readdirSync, statSync } from 'fs';

tmp.setGracefulCleanup();

Expand Down Expand Up @@ -246,10 +247,6 @@ export class Project {
this.autoBaseDir();
fixturify.writeSync(this.baseDir, this.files);
fs.outputJSONSync(path.join(this.baseDir, 'package.json'), this.pkgJSONWithDeps(), { spaces: 2 });

for (let [name, { dir: target }] of this.dependencyLinks) {
fs.ensureSymlinkSync(target, path.join(this.baseDir, 'node_modules', name), 'dir');
}
for (let dep of this.dependencyProjects()) {
dep.baseDir = path.join(this.baseDir, 'node_modules', dep.name);
dep.writeSync();
Expand All @@ -258,6 +255,67 @@ export class Project {
dep.baseDir = path.join(this.baseDir, 'node_modules', dep.name);
dep.writeSync();
}
for (let [name, { dir: target }] of this.dependencyLinks) {
this.writeLinkedPackage(name, target);
}
}

private writeLinkedPackage(name: string, target: string) {
let targetPkg = require(path.join(target, 'package.json'));
let { peerDependencies } = targetPkg;
let overriddenPeers = new Map();
if (peerDependencies) {
for (let peerName of Object.keys(peerDependencies)) {
let theirTarget = resolvePackagePath(peerName, target);
let ourTarget = resolvePackagePath(peerName, this.baseDir);
if (theirTarget !== ourTarget) {
overriddenPeers.set(peerName, ourTarget);
}
}
}

let destination = path.join(this.baseDir, 'node_modules', name);

if (overriddenPeers.size === 0) {
// no peerDeps, so we can just symlink the whole package
fs.ensureSymlinkSync(target, destination, 'dir');
return;
}

// need to reproduce the package structure in our own location
this.hardLinkContents(target, destination);

for (let section of ['dependencies', 'peerDependencies']) {
if (targetPkg[section]) {
for (let depName of Object.keys(targetPkg[section])) {
let depTarget = overriddenPeers.get(depName);
if (!depTarget) {
depTarget = resolvePackagePath(depName, target);
}
if (!depTarget) {
throw new Error(`package ${name} in ${target} depends on ${depName} but we could not resolve it`);
}
fs.ensureSymlinkSync(
depTarget.slice(0, -1 * '/package.json'.length),
path.join(destination, 'node_modules', depName)
);
}
}
}
}

private hardLinkContents(target: string, destination: string, exclude = 'node_modules') {
for (let name of readdirSync(target)) {
if (name === exclude) {
continue;
}
let stat = statSync(path.join(target, name));
if (stat.isDirectory()) {
this.hardLinkContents(path.join(target, name), path.join(destination, name));
} else {
fs.ensureLinkSync(path.join(target, name), path.join(destination, name));
}
}
}

static fromDir(root: string, opts?: ReadDirOpts): Project {
Expand Down

0 comments on commit 84cb4bb

Please sign in to comment.