fix: hoisting in a workspace with no root package

close #2735
PR #2758
This commit is contained in:
Zoltan Kochan
2020-08-09 03:22:28 +03:00
committed by GitHub
parent 507fa1e6a3
commit 400f419765
11 changed files with 458 additions and 6 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/headless": patch
---
Hoisting should work in a workspace that has no root package.

View File

@@ -0,0 +1 @@
lockfile-directory=..

View File

@@ -0,0 +1,7 @@
{
"name": "pkg",
"version": "1.0.0",
"dependencies": {
"express": "4.17.1"
}
}

View File

@@ -0,0 +1,396 @@
importers:
pkg:
dependencies:
express: 4.17.1
specifiers:
express: 4.17.1
lockfileVersion: 5.1
packages:
/accepts/1.3.7:
dependencies:
mime-types: 2.1.27
negotiator: 0.6.2
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
/array-flatten/1.1.1:
dev: false
resolution:
integrity: sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
/body-parser/1.19.0:
dependencies:
bytes: 3.1.0
content-type: 1.0.4
debug: 2.6.9
depd: 1.1.2
http-errors: 1.7.2
iconv-lite: 0.4.24
on-finished: 2.3.0
qs: 6.7.0
raw-body: 2.4.0
type-is: 1.6.18
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
/bytes/3.1.0:
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
/content-disposition/0.5.3:
dependencies:
safe-buffer: 5.1.2
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
/content-type/1.0.4:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
/cookie-signature/1.0.6:
dev: false
resolution:
integrity: sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
/cookie/0.4.0:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
/debug/2.6.9:
dependencies:
ms: 2.0.0
dev: false
resolution:
integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
/depd/1.1.2:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
/destroy/1.0.4:
dev: false
resolution:
integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
/ee-first/1.1.1:
dev: false
resolution:
integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
/encodeurl/1.0.2:
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
/escape-html/1.0.3:
dev: false
resolution:
integrity: sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
/etag/1.8.1:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
/express/4.17.1:
dependencies:
accepts: 1.3.7
array-flatten: 1.1.1
body-parser: 1.19.0
content-disposition: 0.5.3
content-type: 1.0.4
cookie: 0.4.0
cookie-signature: 1.0.6
debug: 2.6.9
depd: 1.1.2
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
finalhandler: 1.1.2
fresh: 0.5.2
merge-descriptors: 1.0.1
methods: 1.1.2
on-finished: 2.3.0
parseurl: 1.3.3
path-to-regexp: 0.1.7
proxy-addr: 2.0.6
qs: 6.7.0
range-parser: 1.2.1
safe-buffer: 5.1.2
send: 0.17.1
serve-static: 1.14.1
setprototypeof: 1.1.1
statuses: 1.5.0
type-is: 1.6.18
utils-merge: 1.0.1
vary: 1.1.2
dev: false
engines:
node: '>= 0.10.0'
resolution:
integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
/finalhandler/1.1.2:
dependencies:
debug: 2.6.9
encodeurl: 1.0.2
escape-html: 1.0.3
on-finished: 2.3.0
parseurl: 1.3.3
statuses: 1.5.0
unpipe: 1.0.0
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
/forwarded/0.1.2:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
/fresh/0.5.2:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
/http-errors/1.7.2:
dependencies:
depd: 1.1.2
inherits: 2.0.3
setprototypeof: 1.1.1
statuses: 1.5.0
toidentifier: 1.0.0
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
/http-errors/1.7.3:
dependencies:
depd: 1.1.2
inherits: 2.0.4
setprototypeof: 1.1.1
statuses: 1.5.0
toidentifier: 1.0.0
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
/iconv-lite/0.4.24:
dependencies:
safer-buffer: 2.1.2
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
/inherits/2.0.3:
dev: false
resolution:
integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
/inherits/2.0.4:
dev: false
resolution:
integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
/ipaddr.js/1.9.1:
dev: false
engines:
node: '>= 0.10'
resolution:
integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
/media-typer/0.3.0:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
/merge-descriptors/1.0.1:
dev: false
resolution:
integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
/methods/1.1.2:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
/mime-db/1.44.0:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
/mime-types/2.1.27:
dependencies:
mime-db: 1.44.0
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
/mime/1.6.0:
dev: false
engines:
node: '>=4'
hasBin: true
resolution:
integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
/ms/2.0.0:
dev: false
resolution:
integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
/ms/2.1.1:
dev: false
resolution:
integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
/negotiator/0.6.2:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
/on-finished/2.3.0:
dependencies:
ee-first: 1.1.1
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
/parseurl/1.3.3:
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
/path-to-regexp/0.1.7:
dev: false
resolution:
integrity: sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
/proxy-addr/2.0.6:
dependencies:
forwarded: 0.1.2
ipaddr.js: 1.9.1
dev: false
engines:
node: '>= 0.10'
resolution:
integrity: sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
/qs/6.7.0:
dev: false
engines:
node: '>=0.6'
resolution:
integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
/range-parser/1.2.1:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
/raw-body/2.4.0:
dependencies:
bytes: 3.1.0
http-errors: 1.7.2
iconv-lite: 0.4.24
unpipe: 1.0.0
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
/safe-buffer/5.1.2:
dev: false
resolution:
integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
/safer-buffer/2.1.2:
dev: false
resolution:
integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
/send/0.17.1:
dependencies:
debug: 2.6.9
depd: 1.1.2
destroy: 1.0.4
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
fresh: 0.5.2
http-errors: 1.7.3
mime: 1.6.0
ms: 2.1.1
on-finished: 2.3.0
range-parser: 1.2.1
statuses: 1.5.0
dev: false
engines:
node: '>= 0.8.0'
resolution:
integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
/serve-static/1.14.1:
dependencies:
encodeurl: 1.0.2
escape-html: 1.0.3
parseurl: 1.3.3
send: 0.17.1
dev: false
engines:
node: '>= 0.8.0'
resolution:
integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
/setprototypeof/1.1.1:
dev: false
resolution:
integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
/statuses/1.5.0:
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
/toidentifier/1.0.0:
dev: false
engines:
node: '>=0.6'
resolution:
integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
/type-is/1.6.18:
dependencies:
media-typer: 0.3.0
mime-types: 2.1.27
dev: false
engines:
node: '>= 0.6'
resolution:
integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
/unpipe/1.0.0:
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
/utils-merge/1.0.1:
dev: false
engines:
node: '>= 0.4.0'
resolution:
integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
/vary/1.1.2:
dev: false
engines:
node: '>= 0.8'
resolution:
integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=

View File

View File

@@ -23,6 +23,7 @@
"@pnpm/package-store": "workspace:*",
"@pnpm/read-projects-context": "workspace:*",
"@pnpm/store-path": "^4.0.2",
"@pnpm/test-fixtures": "workspace:^0.0.0",
"@types/fs-extra": "^9.0.1",
"@types/mz": "^2.7.1",
"@types/ramda": "^0.27.14",

View File

@@ -240,9 +240,8 @@ export default async (opts: HeadlessOptions) => {
})
}
const rootImporterWithFlatModules = (opts.hoistPattern || opts.publicHoistPattern) && opts.projects.find(({ id }) => id === '.')
let newHoistedDependencies!: HoistedDependencies
if (rootImporterWithFlatModules) {
if (opts.hoistPattern || opts.publicHoistPattern) {
newHoistedDependencies = await hoist({
lockfile: filteredLockfile,
lockfileDir,

View File

@@ -13,6 +13,7 @@ import { read as readModulesYaml } from '@pnpm/modules-yaml'
import { fromDir as readPackageJsonFromDir } from '@pnpm/read-package-json'
import readprojectsContext from '@pnpm/read-projects-context'
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
import { copyFixture } from '@pnpm/test-fixtures'
import rimraf = require('@zkochan/rimraf')
import loadJsonFile = require('load-json-file')
import fs = require('mz/fs')
@@ -595,6 +596,36 @@ test('installing with publicHoistPattern=*', async (t) => {
t.end()
})
test('installing with publicHoistPattern=* in a project with external lockfile', async (t) => {
const lockfileDir = tempy.directory()
await copyFixture('pkg-with-external-lockfile', lockfileDir)
const prefix = path.join(lockfileDir, 'pkg')
let { projects } = await readprojectsContext(
[
{
rootDir: prefix,
},
],
{ lockfileDir }
)
projects = await Promise.all(
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
)
await headless(await testDefaults({
lockfileDir,
projects,
publicHoistPattern: '*',
}))
const project = assertProject(t, lockfileDir)
t.ok(project.requireModule('accepts'), 'subdep hoisted')
t.end()
})
const ENGINE_DIR = `${process.platform}-${process.arch}-node-${process.version.split('.')[0]}`
test('using side effects cache', async (t) => {

2
pnpm-lock.yaml generated
View File

@@ -684,6 +684,7 @@ importers:
'@pnpm/package-store': 'link:../package-store'
'@pnpm/read-projects-context': 'link:../read-projects-context'
'@pnpm/store-path': 4.0.2
'@pnpm/test-fixtures': 'link:../../privatePackages/test-fixtures'
'@types/fs-extra': 9.0.1
'@types/mz': 2.7.1
'@types/ramda': 0.27.14
@@ -726,6 +727,7 @@ importers:
'@pnpm/store-controller-types': 'workspace:8.0.2'
'@pnpm/store-path': ^4.0.2
'@pnpm/symlink-dependency': 'workspace:3.0.9'
'@pnpm/test-fixtures': 'workspace:^0.0.0'
'@pnpm/types': 'workspace:6.2.0'
'@types/fs-extra': ^9.0.1
'@types/mz': ^2.7.1

View File

@@ -31,7 +31,7 @@
"repository": "https://github.com/pnpm/pnpm/blob/master/privatePackages/test-fixtures",
"scripts": {
"lint": "tslint -c ../../tslint.json --project .",
"tsc": "rimraf lib && tsc",
"compile": "rimraf lib && tsc",
"test": "pnpm run tsc"
},
"dependencies": {

View File

@@ -1,13 +1,23 @@
import fs = require('fs')
import ncpCB = require('ncp')
import path = require('path')
import { promisify } from 'util'
const ncp = promisify(ncpCB)
export function copyFixture (fixtureName: string, dest: string) {
return ncp(pathToLocalPkg(fixtureName), dest)
export async function copyFixture (fixtureName: string, dest: string) {
const fixturePath = pathToLocalPkg(fixtureName)
if (!fixturePath) throw new Error(`${fixtureName} not found`)
return ncp(fixturePath, dest)
}
export function pathToLocalPkg (pkgName: string) {
return path.join(__dirname, '..', 'fixtures', pkgName)
let dir = __dirname
const { root } = path.parse(dir)
while (true) {
const checkDir = path.join(dir, 'fixtures', pkgName)
if (fs.existsSync(checkDir)) return checkDir
if (dir === root) return null
dir = path.dirname(dir)
}
}