Skip to content

Commit

Permalink
Adds a test for nested workspace hoisting
Browse files Browse the repository at this point in the history
  • Loading branch information
larixer committed Sep 17, 2021
1 parent 1276607 commit 9ff124d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
Expand Up @@ -1405,4 +1405,53 @@ describe(`Node_Modules`, () => {
},
),
);

it(`should properly hoist nested workspaces`,
makeTemporaryEnv(
{
workspaces: [`ws`, `ws/nested1`, `ws/nested1/nested2`],
dependencies: {
ws: `workspace:*`,
nested1: `workspace:*`,
nested2: `workspace:*`,
},
},
{
nodeLinker: `node-modules`,
},
async ({path, run, source}) => {
await xfs.mkdirpPromise(ppath.join(path, `ws/nested1/nested2` as PortablePath));

await xfs.writeJsonPromise(ppath.join(path, `ws/${Filename.manifest}` as PortablePath), {
name: `ws`,
dependencies: {
[`no-deps`]: `1.0.0`,
},
});

await xfs.writeJsonPromise(ppath.join(path, `ws/nested1/${Filename.manifest}` as PortablePath), {
name: `nested1`,
dependencies: {
[`no-deps`]: `2.0.0`,
},
});

await xfs.writeJsonPromise(ppath.join(path, `ws/nested1/nested2/${Filename.manifest}` as PortablePath), {
name: `nested2`,
dependencies: {
[`no-deps`]: `2.0.0`,
},
});

await run(`install`);

await expect(source(`require('no-deps')`)).resolves.toMatchObject({
version: `1.0.0`,
});
await expect(source(`require('module').createRequire(require.resolve('nested1/package.json') + '/..')('no-deps')`)).resolves.toMatchObject({
version: `2.0.0`,
});
},
),
);
});
21 changes: 12 additions & 9 deletions packages/yarnpkg-nm/sources/buildNodeModulesTree.ts
Expand Up @@ -173,7 +173,7 @@ const buildWorkspaceMap = (pnp: PnpApi): WorkspaceMap => {
const workspaceTree: WorkspaceTree = {children: new Map()};
const pnpRoots = pnp.getDependencyTreeRoots();
// Workspace and internal portal locations to locators map
const workspaceLikeLocators = new Map<NativePath, PhysicalPackageLocator>();
const workspaceLikeLocators = new Map<PortablePath, PhysicalPackageLocator>();

const seen = new Set();
const visit = (locator: PhysicalPackageLocator) => {
Expand All @@ -186,7 +186,7 @@ const buildWorkspaceMap = (pnp: PnpApi): WorkspaceMap => {
const pkg = pnp.getPackageInformation(locator);
if (pkg) {
if (pkg.linkType === LinkType.SOFT && !isExternalSoftLink(pkg, locator, pnp, topPkgPortableLocation))
workspaceLikeLocators.set(pkg.packageLocation, locator);
workspaceLikeLocators.set(getRealPackageLocation(pkg, locator, pnp), locator);

for (const [name, referencish] of pkg.packageDependencies) {
if (referencish !== null) {
Expand Down Expand Up @@ -252,7 +252,6 @@ const buildPackageTree = (pnp: PnpApi, options: NodeModulesTreeOptions): { packa

const hoistingLimits = new Map<LocatorKey, Set<string>>();
const workspaceMap = buildWorkspaceMap(pnp);
console.log(`workspace map`, require(`util`).inspect(workspaceMap, false, null));

const topPkg = pnp.getPackageInformation(pnp.topLevel);
if (topPkg === null)
Expand Down Expand Up @@ -420,10 +419,18 @@ const buildPackageTree = (pnp: PnpApi, options: NodeModulesTreeOptions): { packa

addPackageToTree(topLocator.name, topPkg, topLocator, packageTree, topPkg, topPkg.packageDependencies, PortablePath.dot, false);

console.log(`package tree`, require(`util`).inspect(packageTree, false, null));
return {packageTree, hoistingLimits, errors, preserveSymlinksRequired};
};


function getRealPackageLocation(pkg: PackageInformation<NativePath>, locator: PhysicalPackageLocator, pnp: PnpApi): PortablePath {
const realPath = pnp.resolveVirtual && locator.reference && locator.reference.startsWith(`virtual:`)
? pnp.resolveVirtual(pkg.packageLocation)
: pkg.packageLocation;

return npath.toPortablePath(realPath || pkg.packageLocation);
}

function getTargetLocatorPath(locator: PhysicalPackageLocator, pnp: PnpApi, options: NodeModulesTreeOptions): {linkType: LinkType, target: PortablePath} {
const pkgLocator = pnp.getLocator(locator.name.replace(WORKSPACE_NAME_SUFFIX, ``), locator.reference);

Expand All @@ -442,11 +449,7 @@ function getTargetLocatorPath(locator: PhysicalPackageLocator, pnp: PnpApi, opti
target = npath.toPortablePath(info.packageLocation);
linkType = LinkType.SOFT;
} else {
const truePath = pnp.resolveVirtual && locator.reference && locator.reference.startsWith(`virtual:`)
? pnp.resolveVirtual(info.packageLocation)
: info.packageLocation;

target = npath.toPortablePath(truePath || info.packageLocation);
target = getRealPackageLocation(info, locator, pnp);
linkType = info.linkType;
}
return {linkType, target};
Expand Down

0 comments on commit 9ff124d

Please sign in to comment.