Skip to content

Commit 8c1f26c

Browse files
gregmagolanalexeagle
authored andcommitted
fix: simplify portion of linker and fix case where runfiles node_modules symlinks are missing under bazel run
1 parent ac5502c commit 8c1f26c

File tree

2 files changed

+74
-139
lines changed

2 files changed

+74
-139
lines changed

internal/linker/index.js

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -320,63 +320,37 @@ function main(args, runfiles) {
320320
}
321321
for (const packagePath of Object.keys(roots)) {
322322
const workspace = roots[packagePath];
323-
if (workspace) {
324-
const workspaceNodeModules = yield resolveWorkspaceNodeModules(workspace, startCwd, isExecroot, execroot, runfiles);
323+
let workspaceNodeModules = yield resolveWorkspaceNodeModules(workspace, startCwd, isExecroot, execroot, runfiles);
324+
if (yield exists(workspaceNodeModules)) {
325325
log_verbose(`resolved ${workspace} workspace node modules path to ${workspaceNodeModules}`);
326-
if (packagePath) {
327-
if (yield exists(workspaceNodeModules)) {
328-
yield mkdirp(packagePath);
329-
yield symlinkWithUnlink(workspaceNodeModules, `${packagePath}/node_modules`);
330-
if (!isExecroot) {
331-
const runfilesPackagePath = `${startCwd}/${packagePath}`;
332-
if (yield exists(runfilesPackagePath)) {
333-
yield symlinkWithUnlink(`${packagePath}/node_modules`, `${runfilesPackagePath}/node_modules`);
334-
}
335-
}
336-
const packagePathBin = `${bin}/${packagePath}`;
337-
if (yield exists(packagePathBin)) {
338-
yield symlinkWithUnlink(`${packagePath}/node_modules`, `${packagePathBin}/node_modules`);
339-
}
340-
}
341-
else {
342-
log_verbose(`no npm workspace node_modules folder under ${packagePath} to link to; creating node_modules directories in ${process.cwd()} for ${packagePath} 1p deps`);
343-
yield mkdirp(`${packagePath}/node_modules`);
344-
if (!isExecroot) {
345-
const runfilesPackagePath = `${startCwd}/${packagePath}`;
346-
yield mkdirp(`${runfilesPackagePath}/node_modules`);
347-
yield symlinkWithUnlink(`${packagePath}/node_modules`, `${runfilesPackagePath}/node_modules`);
348-
}
349-
const packagePathBin = `${bin}/${packagePath}`;
350-
yield mkdirp(`${packagePathBin}/node_modules`);
351-
yield symlinkWithUnlink(`${packagePath}/node_modules`, `${packagePathBin}/node_modules`);
352-
}
353-
}
354-
else {
355-
if (yield exists(workspaceNodeModules)) {
356-
yield symlinkWithUnlink(workspaceNodeModules, `node_modules`);
357-
}
358-
else {
359-
log_verbose(`no root npm workspace node_modules folder to link to; creating node_modules directory in ${process.cwd()}`);
360-
yield mkdirp('node_modules');
361-
}
362-
}
363326
}
364327
else {
365-
if (packagePath) {
366-
log_verbose(`no 3p deps at ${packagePath}; creating node_modules directories in ${process.cwd()} for ${packagePath} 1p deps`);
367-
yield mkdirp(`${packagePath}/node_modules`);
368-
if (!isExecroot) {
369-
const runfilesPackagePath = `${startCwd}/${packagePath}`;
370-
yield mkdirp(`${runfilesPackagePath}/node_modules`);
371-
yield symlinkWithUnlink(`${packagePath}/node_modules`, `${runfilesPackagePath}/node_modules`);
372-
}
373-
const packagePathBin = `${bin}/${packagePath}`;
374-
yield mkdirp(`${packagePathBin}/node_modules`);
375-
yield symlinkWithUnlink(`${packagePath}/node_modules`, `${packagePathBin}/node_modules`);
376-
}
377-
else {
378-
log_verbose(`no 3p deps at root; creating node_modules directory in ${process.cwd()} for root 1p deps`);
379-
yield mkdirp('node_modules');
328+
workspaceNodeModules = undefined;
329+
}
330+
if (packagePath) {
331+
yield mkdirp(packagePath);
332+
}
333+
const execrootNodeModules = path.posix.join(packagePath, `node_modules`);
334+
if (workspaceNodeModules) {
335+
yield symlinkWithUnlink(workspaceNodeModules, execrootNodeModules);
336+
}
337+
else {
338+
yield mkdirp(execrootNodeModules);
339+
}
340+
const packagePathBin = path.posix.join(bin, packagePath);
341+
yield mkdirp(`${packagePathBin}`);
342+
yield symlinkWithUnlink(execrootNodeModules, `${packagePathBin}/node_modules`);
343+
if (!isExecroot) {
344+
const runfilesPackagePath = path.posix.join(startCwd, packagePath);
345+
yield mkdirp(`${runfilesPackagePath}`);
346+
yield symlinkWithUnlink(execrootNodeModules, `${runfilesPackagePath}/node_modules`);
347+
}
348+
if (process.env['RUNFILES']) {
349+
const stat = yield gracefulLstat(process.env['RUNFILES']);
350+
if (stat && stat.isDirectory()) {
351+
const runfilesPackagePath = path.posix.join(process.env['RUNFILES'], packagePath);
352+
yield mkdirp(`${runfilesPackagePath}`);
353+
yield symlinkWithUnlink(execrootNodeModules, `${runfilesPackagePath}/node_modules`);
380354
}
381355
}
382356
}

internal/linker/link_node_modules.ts

Lines changed: 46 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -472,94 +472,55 @@ export async function main(args: string[], runfiles: Runfiles) {
472472
// lined to node_modules folders at the root or in sub-directories
473473
for (const packagePath of Object.keys(roots)) {
474474
const workspace = roots[packagePath];
475-
if (workspace) {
476-
const workspaceNodeModules = await resolveWorkspaceNodeModules(
477-
workspace, startCwd, isExecroot, execroot, runfiles);
475+
let workspaceNodeModules: string | undefined = await resolveWorkspaceNodeModules(
476+
workspace, startCwd, isExecroot, execroot, runfiles);
477+
if (await exists(workspaceNodeModules)) {
478478
log_verbose(`resolved ${workspace} workspace node modules path to ${workspaceNodeModules}`);
479+
} else {
480+
// There are no third party node_modules to symlink to
481+
workspaceNodeModules = undefined;
482+
}
479483

480-
if (packagePath) {
481-
// sub-directory node_modules
482-
if (await exists(workspaceNodeModules)) {
483-
// in some cases packagePath may not exist in sandbox if there are no source deps
484-
// and only generated file deps. we create it so that we that we can link to
485-
// packagePath/node_modules since packagePathBin/node_modules is a symlink to
486-
// packagePath/node_modules and is unguarded in launcher.sh as we allow symlinks to fall
487-
// through to from output tree to source tree to prevent resolving the same npm package to
488-
// multiple locations on disk
489-
await mkdirp(packagePath);
490-
await symlinkWithUnlink(workspaceNodeModules, `${packagePath}/node_modules`);
491-
if (!isExecroot) {
492-
// Under runfiles, we symlink into the package in runfiles as well.
493-
// When inside the sandbox, the execroot location will not exist to symlink to.
494-
const runfilesPackagePath = `${startCwd}/${packagePath}`;
495-
if (await exists(runfilesPackagePath)) {
496-
await symlinkWithUnlink(
497-
`${packagePath}/node_modules`, `${runfilesPackagePath}/node_modules`);
498-
}
499-
}
500-
const packagePathBin = `${bin}/${packagePath}`;
501-
if (await exists(packagePathBin)) {
502-
// if bin path exists, symlink bin/package/node_modules -> package/node_modules
503-
// NB: this location is unguarded in launcher.sh to allow symlinks to fall-throught
504-
// package/node_modules to prevent resolving the same npm package to multiple locations
505-
// on disk
506-
await symlinkWithUnlink(
507-
`${packagePath}/node_modules`, `${packagePathBin}/node_modules`);
508-
}
509-
} else {
510-
// Special case if there no target to symlink to for the root workspace, create a
511-
// root node_modules folder for 1st party deps
512-
log_verbose(`no npm workspace node_modules folder under ${
513-
packagePath} to link to; creating node_modules directories in ${process.cwd()} for ${
514-
packagePath} 1p deps`);
515-
await mkdirp(`${packagePath}/node_modules`);
516-
if (!isExecroot) {
517-
// Under runfiles, we symlink into the package in runfiles as well.
518-
// When inside the sandbox, the execroot location will not exist to symlink to.
519-
const runfilesPackagePath = `${startCwd}/${packagePath}`;
520-
await mkdirp(`${runfilesPackagePath}/node_modules`);
521-
await symlinkWithUnlink(
522-
`${packagePath}/node_modules`, `${runfilesPackagePath}/node_modules`);
523-
}
524-
const packagePathBin = `${bin}/${packagePath}`;
525-
await mkdirp(`${packagePathBin}/node_modules`);
526-
await symlinkWithUnlink(`${packagePath}/node_modules`, `${packagePathBin}/node_modules`);
527-
}
528-
} else {
529-
// root node_modules
530-
if (await exists(workspaceNodeModules)) {
531-
await symlinkWithUnlink(workspaceNodeModules, `node_modules`);
532-
} else {
533-
// Special case if there no target to symlink to for the root workspace, create a
534-
// root node_modules folder for 1st party deps
535-
log_verbose(
536-
`no root npm workspace node_modules folder to link to; creating node_modules directory in ${
537-
process.cwd()}`);
538-
await mkdirp('node_modules');
539-
}
540-
}
484+
if (packagePath) {
485+
// In some cases packagePath may not exist in sandbox if there are no source deps
486+
// and only generated file deps. we create it so that we that we can link to
487+
// packagePath/node_modules since packagePathBin/node_modules is a symlink to
488+
// packagePath/node_modules and is unguarded in launcher.sh as we allow symlinks to fall
489+
// through to from output tree to source tree to prevent resolving the same npm package to
490+
// multiple locations on disk
491+
await mkdirp(packagePath);
492+
}
493+
494+
// There are third party modules at this package path
495+
const execrootNodeModules = path.posix.join(packagePath, `node_modules`);
496+
497+
if (workspaceNodeModules) {
498+
// Execroot symlink -> external workspace node_modules
499+
await symlinkWithUnlink(workspaceNodeModules, execrootNodeModules);
541500
} else {
542-
if (packagePath) {
543-
// Special case if there for first party node_modules at root only
544-
log_verbose(`no 3p deps at ${packagePath}; creating node_modules directories in ${
545-
process.cwd()} for ${packagePath} 1p deps`);
546-
await mkdirp(`${packagePath}/node_modules`);
547-
if (!isExecroot) {
548-
// Under runfiles, we symlink into the package in runfiles as well.
549-
// When inside the sandbox, the execroot location will not exist to symlink to.
550-
const runfilesPackagePath = `${startCwd}/${packagePath}`;
551-
await mkdirp(`${runfilesPackagePath}/node_modules`);
552-
await symlinkWithUnlink(
553-
`${packagePath}/node_modules`, `${runfilesPackagePath}/node_modules`);
554-
}
555-
const packagePathBin = `${bin}/${packagePath}`;
556-
await mkdirp(`${packagePathBin}/node_modules`);
557-
await symlinkWithUnlink(`${packagePath}/node_modules`, `${packagePathBin}/node_modules`);
558-
} else {
559-
// Special case if there for first party node_modules at root only
560-
log_verbose(`no 3p deps at root; creating node_modules directory in ${
561-
process.cwd()} for root 1p deps`);
562-
await mkdirp('node_modules');
501+
// Create an execroot node_modules directory since there are no third party node_modules to symlink to
502+
await mkdirp(execrootNodeModules);
503+
}
504+
505+
// Bin symlink -> execroot node_modules
506+
const packagePathBin = path.posix.join(bin, packagePath);
507+
await mkdirp(`${packagePathBin}`);
508+
await symlinkWithUnlink(execrootNodeModules, `${packagePathBin}/node_modules`);
509+
510+
// Start CWD symlink -> execroot node_modules
511+
if (!isExecroot) {
512+
const runfilesPackagePath = path.posix.join(startCwd, packagePath);
513+
await mkdirp(`${runfilesPackagePath}`);
514+
await symlinkWithUnlink(execrootNodeModules, `${runfilesPackagePath}/node_modules`);
515+
}
516+
517+
// RUNFILES symlink -> execroot node_modules
518+
if (process.env['RUNFILES']) {
519+
const stat = await gracefulLstat(process.env['RUNFILES']);
520+
if (stat && stat.isDirectory()) {
521+
const runfilesPackagePath = path.posix.join(process.env['RUNFILES'], packagePath);
522+
await mkdirp(`${runfilesPackagePath}`);
523+
await symlinkWithUnlink(execrootNodeModules, `${runfilesPackagePath}/node_modules`);
563524
}
564525
}
565526
}

0 commit comments

Comments
 (0)