From b7e044e6324352d7b56dbc58b0feb2a30eab4c0a Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 5 Aug 2019 23:42:46 +0300 Subject: [PATCH] fix(list): should not fail on skipped deps --- packages/dependencies-hierarchy/src/index.ts | 104 ++++++++++++------ .../test/circularTree.json | 42 +++++++ packages/dependencies-hierarchy/test/index.ts | 64 +++++++++++ packages/list/src/renderTree.ts | 3 + packages/list/test/index.ts | 30 +++++ packages/pnpm/test/list.ts | 20 ++++ 6 files changed, 231 insertions(+), 32 deletions(-) diff --git a/packages/dependencies-hierarchy/src/index.ts b/packages/dependencies-hierarchy/src/index.ts index 29cc7b4c5f..60d8bbd82c 100644 --- a/packages/dependencies-hierarchy/src/index.ts +++ b/packages/dependencies-hierarchy/src/index.ts @@ -1,8 +1,10 @@ import { getLockfileImporterId, LockfileImporter, + PackageSnapshot, PackageSnapshots, readCurrentLockfile, + readWantedLockfile, } from '@pnpm/lockfile-file' import { nameVerFromPkgSnapshot, @@ -11,7 +13,11 @@ import { import { read as readModulesYaml } from '@pnpm/modules-yaml' import readModulesDir from '@pnpm/read-modules-dir' import { DEPENDENCIES_FIELDS, DependenciesField, Registries } from '@pnpm/types' -import { normalizeRegistries, safeReadPackageFromDir } from '@pnpm/utils' +import { + normalizeRegistries, + realNodeModulesDir, + safeReadPackageFromDir, +} from '@pnpm/utils' import assert = require('assert') import { refToAbsolute, refToRelative } from 'dependency-path' import minimatch = require('minimatch') @@ -31,6 +37,8 @@ export interface PackageNode { dependencies?: PackageNode[], dev?: boolean, isPeer: boolean, + isSkipped: boolean, + isMissing: boolean, name: string, optional?: true, path: string, @@ -84,15 +92,16 @@ async function dependenciesHierarchy ( lockfileDirectory?: string, }, ): Promise { - const modules = await readModulesYaml(projectPath) + const lockfileDirectory = maybeOpts && maybeOpts.lockfileDirectory || projectPath + const virtualStoreDir = await realNodeModulesDir(lockfileDirectory) + const modules = await readModulesYaml(virtualStoreDir) const registries = normalizeRegistries({ ...maybeOpts && maybeOpts.registries, ...modules && modules.registries, }) - const lockfileDirectory = maybeOpts && maybeOpts.lockfileDirectory || projectPath - const lockfile = await readCurrentLockfile(lockfileDirectory, { ignoreIncompatible: false }) + const currentLockfile = await readCurrentLockfile(lockfileDirectory, { ignoreIncompatible: false }) - if (!lockfile) return {} + if (!currentLockfile) return {} const opts = { depth: 0, @@ -105,33 +114,39 @@ async function dependenciesHierarchy ( } const importerId = getLockfileImporterId(lockfileDirectory, projectPath) - if (!lockfile.importers[importerId]) return {} + if (!currentLockfile.importers[importerId]) return {} const modulesDir = path.join(projectPath, 'node_modules') - const savedDeps = getAllDirectDependencies(lockfile.importers[importerId]) + const savedDeps = getAllDirectDependencies(currentLockfile.importers[importerId]) const allDirectDeps = await readModulesDir(modulesDir) || [] const unsavedDeps = allDirectDeps.filter((directDep) => !savedDeps[directDep]) + const wantedLockfile = await readWantedLockfile(lockfileDirectory, { ignoreIncompatible: false }) || { packages: {} } const getChildrenTree = getTree.bind(null, { currentDepth: 1, + currentPackages: currentLockfile.packages, includeOptionalDependencies: include.optionalDependencies === true, maxDepth: opts.depth, modulesDir, registries, searched, - }, lockfile.packages) + skipped: new Set(modules && modules.skipped || []), + wantedPackages: wantedLockfile.packages || {}, + }) const result: DependenciesHierarchy = {} for (const dependenciesField of DEPENDENCIES_FIELDS.sort().filter(dependenciedField => include[dependenciedField])) { - const topDeps = lockfile.importers[importerId][dependenciesField] || {} + const topDeps = currentLockfile.importers[importerId][dependenciesField] || {} result[dependenciesField] = [] Object.keys(topDeps).forEach((alias) => { const { packageInfo, packageAbsolutePath } = getPkgInfo({ alias, + currentPackages: currentLockfile.packages || {}, modulesDir, - packages: lockfile.packages || {}, ref: topDeps[alias], registries, + skipped: new Set(modules && modules.skipped || []), + wantedPackages: wantedLockfile.packages || {}, }) let newEntry: PackageNode | null = null const matchedSearched = searched.length && matches(searched, packageInfo) @@ -140,14 +155,16 @@ async function dependenciesHierarchy ( newEntry = packageInfo } else { const relativeId = refToRelative(topDeps[alias], alias) - const dependencies = getChildrenTree([relativeId], relativeId) - if (dependencies.length) { - newEntry = { - ...packageInfo, - dependencies, + if (relativeId) { + const dependencies = getChildrenTree([relativeId], relativeId) + if (dependencies.length) { + newEntry = { + ...packageInfo, + dependencies, + } + } else if (!searched.length || matches(searched, packageInfo)) { + newEntry = packageInfo } - } else if (!searched.length || matches(searched, packageInfo)) { - newEntry = packageInfo } } if (newEntry) { @@ -173,7 +190,9 @@ async function dependenciesHierarchy ( } const pkg = { alias: unsavedDep, + isMissing: false, isPeer: false, + isSkipped: false, name: unsavedDep, path: pkgPath, version, @@ -207,19 +226,21 @@ function getTree ( modulesDir: string, includeOptionalDependencies: boolean, searched: PackageSelector[], + skipped: Set, registries: Registries, + currentPackages: PackageSnapshots, + wantedPackages: PackageSnapshots, }, - packages: PackageSnapshots, keypath: string[], parentId: string, ): PackageNode[] { - if (opts.currentDepth > opts.maxDepth || !packages || !packages[parentId]) return [] + if (opts.currentDepth > opts.maxDepth || !opts.currentPackages || !opts.currentPackages[parentId]) return [] const deps = opts.includeOptionalDependencies === false - ? packages[parentId].dependencies + ? opts.currentPackages[parentId].dependencies : { - ...packages[parentId].dependencies, - ...packages[parentId].optionalDependencies, + ...opts.currentPackages[parentId].dependencies, + ...opts.currentPackages[parentId].optionalDependencies, } if (!deps) return [] @@ -227,18 +248,20 @@ function getTree ( const getChildrenTree = getTree.bind(null, { ...opts, currentDepth: opts.currentDepth + 1, - }, packages) + }) - const peers = new Set(Object.keys(packages[parentId].peerDependencies || {})) + const peers = new Set(Object.keys(opts.currentPackages[parentId].peerDependencies || {})) const result: PackageNode[] = [] Object.keys(deps).forEach((alias) => { const { packageInfo, packageAbsolutePath } = getPkgInfo({ alias, + currentPackages: opts.currentPackages, modulesDir: opts.modulesDir, - packages, peers, ref: deps[alias], registries: opts.registries, + skipped: opts.skipped, + wantedPackages: opts.wantedPackages, }) let circular: boolean const matchedSearched = opts.searched.length && matches(opts.searched, packageInfo) @@ -278,9 +301,11 @@ function getPkgInfo ( alias: string, modulesDir: string, ref: string, - packages: PackageSnapshots, + currentPackages: PackageSnapshots, peers?: Set, registries: Registries, + skipped: Set, + wantedPackages: PackageSnapshots, }, ) { let name!: string @@ -288,14 +313,27 @@ function getPkgInfo ( let resolved: string | undefined = undefined let dev: boolean | undefined = undefined let optional: true | undefined = undefined + let isSkipped: boolean = false + let isMissing: boolean = false const relDepPath = refToRelative(opts.ref, opts.alias) if (relDepPath) { - const parsed = nameVerFromPkgSnapshot(relDepPath, opts.packages[relDepPath]) - name = parsed.name - version = parsed.version - resolved = pkgSnapshotToResolution(relDepPath, opts.packages[relDepPath], opts.registries)['tarball'] - dev = opts.packages[relDepPath].dev - optional = opts.packages[relDepPath].optional + let pkgSnapshot!: PackageSnapshot + if (opts.currentPackages[relDepPath]) { + pkgSnapshot = opts.currentPackages[relDepPath] + const parsed = nameVerFromPkgSnapshot(relDepPath, pkgSnapshot) + name = parsed.name + version = parsed.version + } else { + pkgSnapshot = opts.wantedPackages[relDepPath] + const parsed = nameVerFromPkgSnapshot(relDepPath, pkgSnapshot) + name = parsed.name + version = parsed.version + isMissing = true + isSkipped = opts.skipped.has(relDepPath) + } + resolved = pkgSnapshotToResolution(relDepPath, pkgSnapshot, opts.registries)['tarball'] + dev = pkgSnapshot.dev + optional = pkgSnapshot.optional } else { name = opts.alias version = opts.ref @@ -303,7 +341,9 @@ function getPkgInfo ( const packageAbsolutePath = refToAbsolute(opts.ref, opts.alias, opts.registries) const packageInfo = { alias: opts.alias, + isMissing, isPeer: Boolean(opts.peers && opts.peers.has(opts.alias)), + isSkipped, name, path: packageAbsolutePath && path.join(opts.modulesDir, `.${packageAbsolutePath}`) || path.join(opts.modulesDir, '..', opts.ref.substr(5)), version, diff --git a/packages/dependencies-hierarchy/test/circularTree.json b/packages/dependencies-hierarchy/test/circularTree.json index 6eb0b23e6f..601142c944 100644 --- a/packages/dependencies-hierarchy/test/circularTree.json +++ b/packages/dependencies-hierarchy/test/circularTree.json @@ -3,7 +3,9 @@ { "path": "registry.npmjs.org/es6-iterator/2.0.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", "name": "es6-iterator", "version": "2.0.1", @@ -11,7 +13,9 @@ { "path": "registry.npmjs.org/d/1.0.0", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "name": "d", "version": "1.0.0", @@ -19,7 +23,9 @@ { "path": "registry.npmjs.org/es5-ext/0.10.24", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "name": "es5-ext", "version": "0.10.24", @@ -27,7 +33,9 @@ { "path": "registry.npmjs.org/es6-iterator/2.0.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", "name": "es6-iterator", "version": "2.0.1", @@ -36,7 +44,9 @@ { "path": "registry.npmjs.org/es6-symbol/3.1.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "name": "es6-symbol", "version": "3.1.1", @@ -44,7 +54,9 @@ { "path": "registry.npmjs.org/d/1.0.0", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "name": "d", "version": "1.0.0", @@ -53,7 +65,9 @@ { "path": "registry.npmjs.org/es5-ext/0.10.24", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "name": "es5-ext", "version": "0.10.24", @@ -68,7 +82,9 @@ { "path": "registry.npmjs.org/es5-ext/0.10.24", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "name": "es5-ext", "version": "0.10.24", @@ -76,7 +92,9 @@ { "path": "registry.npmjs.org/es6-iterator/2.0.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", "name": "es6-iterator", "version": "2.0.1", @@ -85,7 +103,9 @@ { "path": "registry.npmjs.org/es6-symbol/3.1.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "name": "es6-symbol", "version": "3.1.1", @@ -93,7 +113,9 @@ { "path": "registry.npmjs.org/d/1.0.0", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "name": "d", "version": "1.0.0", @@ -101,7 +123,9 @@ { "path": "registry.npmjs.org/es5-ext/0.10.24", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "name": "es5-ext", "version": "0.10.24", @@ -112,7 +136,9 @@ { "path": "registry.npmjs.org/es5-ext/0.10.24", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "name": "es5-ext", "version": "0.10.24", @@ -125,7 +151,9 @@ { "path": "registry.npmjs.org/es6-symbol/3.1.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "name": "es6-symbol", "version": "3.1.1", @@ -133,7 +161,9 @@ { "path": "registry.npmjs.org/d/1.0.0", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "name": "d", "version": "1.0.0", @@ -141,7 +171,9 @@ { "path": "registry.npmjs.org/es5-ext/0.10.24", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "name": "es5-ext", "version": "0.10.24", @@ -149,7 +181,9 @@ { "path": "registry.npmjs.org/es6-iterator/2.0.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", "name": "es6-iterator", "version": "2.0.1", @@ -158,7 +192,9 @@ { "path": "registry.npmjs.org/es6-symbol/3.1.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "name": "es6-symbol", "version": "3.1.1", @@ -171,7 +207,9 @@ { "path": "registry.npmjs.org/es5-ext/0.10.24", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "name": "es5-ext", "version": "0.10.24", @@ -179,7 +217,9 @@ { "path": "registry.npmjs.org/es6-iterator/2.0.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", "name": "es6-iterator", "version": "2.0.1", @@ -188,7 +228,9 @@ { "path": "registry.npmjs.org/es6-symbol/3.1.1", "dev": false, + "isMissing": false, "isPeer": false, + "isSkipped": false, "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "name": "es6-symbol", "version": "3.1.1", diff --git a/packages/dependencies-hierarchy/test/index.ts b/packages/dependencies-hierarchy/test/index.ts index 21fd593a1e..d0d758df96 100644 --- a/packages/dependencies-hierarchy/test/index.ts +++ b/packages/dependencies-hierarchy/test/index.ts @@ -23,7 +23,9 @@ test('one package depth 0', async t => { { alias: 'minimatch', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'minimatch', path: path.join(modulesDir, '.registry.npmjs.org/minimatch/3.0.4'), resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz', @@ -32,7 +34,9 @@ test('one package depth 0', async t => { { alias: 'rimraf', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'rimraf', path: path.join(modulesDir, '.registry.npmjs.org/rimraf/2.5.1'), resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz', @@ -43,7 +47,9 @@ test('one package depth 0', async t => { { alias: 'is-positive', dev: true, + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-positive', path: path.join(modulesDir, '.registry.npmjs.org/is-positive/1.0.0'), resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', @@ -54,7 +60,9 @@ test('one package depth 0', async t => { { alias: 'is-negative', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-negative', optional: true, path: path.join(modulesDir, '.registry.npmjs.org/is-negative/1.0.0'), @@ -76,7 +84,9 @@ test('one package depth 1', async t => { { alias: 'minimatch', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'minimatch', path: path.join(modulesDir, '.registry.npmjs.org/minimatch/3.0.4'), resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz', @@ -86,7 +96,9 @@ test('one package depth 1', async t => { { alias: 'brace-expansion', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'brace-expansion', path: path.join(modulesDir, '.registry.npmjs.org/brace-expansion/1.1.8'), resolved: 'https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz', @@ -97,7 +109,9 @@ test('one package depth 1', async t => { { alias: 'rimraf', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'rimraf', path: path.join(modulesDir, '.registry.npmjs.org/rimraf/2.5.1'), resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz', @@ -107,7 +121,9 @@ test('one package depth 1', async t => { { alias: 'glob', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'glob', path: path.join(modulesDir, '.registry.npmjs.org/glob/6.0.4'), resolved: 'https://registry.npmjs.org/glob/-/glob-6.0.4.tgz', @@ -120,7 +136,9 @@ test('one package depth 1', async t => { { alias: 'is-positive', dev: true, + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-positive', path: path.join(modulesDir, '.registry.npmjs.org/is-positive/1.0.0'), resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', @@ -131,7 +149,9 @@ test('one package depth 1', async t => { { alias: 'is-negative', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-negative', optional: true, path: path.join(modulesDir, '.registry.npmjs.org/is-negative/1.0.0'), @@ -163,7 +183,9 @@ test('only prod depth 0', async t => { { alias: 'minimatch', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'minimatch', path: path.join(modulesDir, '.registry.npmjs.org/minimatch/3.0.4'), resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz', @@ -172,7 +194,9 @@ test('only prod depth 0', async t => { { alias: 'rimraf', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'rimraf', path: path.join(modulesDir, '.registry.npmjs.org/rimraf/2.5.1'), resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz', @@ -203,7 +227,9 @@ test('only dev depth 0', async t => { { alias: 'is-positive', dev: true, + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-positive', path: path.join(modulesDir, '.registry.npmjs.org/is-positive/1.0.0'), resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', @@ -232,7 +258,9 @@ test('filter 1 package with depth 0', async t => { { alias: 'rimraf', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'rimraf', path: path.join(modulesDir, '.registry.npmjs.org/rimraf/2.5.1'), resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz', @@ -255,7 +283,9 @@ test('filter by pattern', async t => { { alias: 'rimraf', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'rimraf', path: path.join(modulesDir, '.registry.npmjs.org/rimraf/2.5.1'), resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz', @@ -278,7 +308,9 @@ test('filter by pattern', async t => { { alias: 'rimraf', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'rimraf', path: path.join(modulesDir, '.registry.npmjs.org/rimraf/2.5.1'), resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz', @@ -312,7 +344,9 @@ test('filter 2 packages with depth 100', async t => { { alias: 'minimatch', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'minimatch', path: path.join(modulesDir, '.registry.npmjs.org/minimatch/3.0.4'), resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz', @@ -322,7 +356,9 @@ test('filter 2 packages with depth 100', async t => { { alias: 'rimraf', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'rimraf', path: path.join(modulesDir, '.registry.npmjs.org/rimraf/2.5.1'), resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz', @@ -332,7 +368,9 @@ test('filter 2 packages with depth 100', async t => { { alias: 'glob', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'glob', path: path.join(modulesDir, '.registry.npmjs.org/glob/6.0.4'), resolved: 'https://registry.npmjs.org/glob/-/glob-6.0.4.tgz', @@ -342,7 +380,9 @@ test('filter 2 packages with depth 100', async t => { { alias: 'inflight', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'inflight', path: path.join(modulesDir, '.registry.npmjs.org/inflight/1.0.6'), resolved: 'https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz', @@ -352,7 +392,9 @@ test('filter 2 packages with depth 100', async t => { { alias: 'once', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'once', path: path.join(modulesDir, '.registry.npmjs.org/once/1.4.0'), resolved: 'https://registry.npmjs.org/once/-/once-1.4.0.tgz', @@ -364,7 +406,9 @@ test('filter 2 packages with depth 100', async t => { { alias: 'minimatch', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'minimatch', path: path.join(modulesDir, '.registry.npmjs.org/minimatch/3.0.4'), resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz', @@ -374,7 +418,9 @@ test('filter 2 packages with depth 100', async t => { { alias: 'once', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'once', path: path.join(modulesDir, '.registry.npmjs.org/once/1.4.0'), resolved: 'https://registry.npmjs.org/once/-/once-1.4.0.tgz', @@ -449,7 +495,9 @@ test('local package depth 0', async t => { dependencies: [ { alias: 'general', + isMissing: false, isPeer: false, + isSkipped: false, name: 'general', path: generalFixture, version: 'link:../general', @@ -457,7 +505,9 @@ test('local package depth 0', async t => { { alias: 'is-positive', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-positive', path: path.join(modulesDir, '.registry.npmjs.org/is-positive/3.1.0'), resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-3.1.0.tgz', @@ -478,7 +528,9 @@ test('on a package that has only links', async t => { dependencies: [ { alias: 'general', + isMissing: false, isPeer: false, + isSkipped: false, name: 'general', path: path.join(__dirname, '..', 'fixtureWithLinks', 'general'), version: 'link:../general', @@ -506,7 +558,9 @@ test('filter on a package that has only links', async t => { dependencies: [ { alias: 'general', + isMissing: false, isPeer: false, + isSkipped: false, name: 'general', path: path.join(__dirname, '..', 'fixtureWithLinks', 'general'), searched: true, @@ -527,7 +581,9 @@ test('unsaved dependencies are listed', async t => { { alias: 'symlink-dir', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'symlink-dir', path: path.join(modulesDir, '.registry.npmjs.org/symlink-dir/2.0.2'), resolved: 'https://registry.npmjs.org/symlink-dir/-/symlink-dir-2.0.2.tgz', @@ -539,14 +595,18 @@ test('unsaved dependencies are listed', async t => { unsavedDependencies: [ { alias: 'general', + isMissing: false, isPeer: false, + isSkipped: false, name: 'general', path: generalFixture, version: 'link:../general', }, { alias: 'is-positive', + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-positive', path: path.join(modulesDir, 'is-positive'), version: '3.1.0', @@ -563,7 +623,9 @@ test('unsaved dependencies are listed and filtered', async t => { { alias: 'symlink-dir', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'symlink-dir', path: path.join(modulesDir, '.registry.npmjs.org/symlink-dir/2.0.2'), resolved: 'https://registry.npmjs.org/symlink-dir/-/symlink-dir-2.0.2.tgz', @@ -590,7 +652,9 @@ test('dependency with an alias', async t => { { alias: 'positive', dev: false, + isMissing: false, isPeer: false, + isSkipped: false, name: 'is-positive', path: path.join(modulesDir, '.registry.npmjs.org/is-positive/1.0.0'), resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', diff --git a/packages/list/src/renderTree.ts b/packages/list/src/renderTree.ts index 75cf5899a8..11d6dd46b1 100644 --- a/packages/list/src/renderTree.ts +++ b/packages/list/src/renderTree.ts @@ -122,6 +122,9 @@ function printLabel (getPkgColor: GetPkgColor, node: PackageNode) { if (node.isPeer) { txt += ' peer' } + if (node.isSkipped) { + txt += ' skipped' + } return txt } diff --git a/packages/list/test/index.ts b/packages/list/test/index.ts index bb6155ce6b..1a0b84944b 100644 --- a/packages/list/test/index.ts +++ b/packages/list/test/index.ts @@ -466,7 +466,9 @@ test('unsaved dependencies are marked', async (t) => { unsavedDependencies: [ { alias: 'foo', + isMissing: false, isPeer: false, + isSkipped: false, name: 'foo', path: '', version: '1.0.0', @@ -501,77 +503,99 @@ test('write long lists in columns', async (t) => { dependencies: [ { alias: 'a', + isMissing: false, isPeer: false, + isSkipped: false, name: 'a', path: '', version: '1.0.0', }, { alias: 'b', + isMissing: false, isPeer: false, + isSkipped: false, name: 'b', path: '', version: '1.0.0', }, { alias: 'c', + isMissing: false, isPeer: false, + isSkipped: false, name: 'c', path: '', version: '1.0.0', }, { alias: 'd', + isMissing: false, isPeer: false, + isSkipped: false, name: 'd', path: '', version: '1.0.0', }, { alias: 'e', + isMissing: false, isPeer: false, + isSkipped: false, name: 'e', path: '', version: '1.0.0', }, { alias: 'f', + isMissing: false, isPeer: false, + isSkipped: false, name: 'f', path: '', version: '1.0.0', }, { alias: 'g', + isMissing: false, isPeer: false, + isSkipped: false, name: 'g', path: '', version: '1.0.0', }, { alias: 'h', + isMissing: false, isPeer: false, + isSkipped: false, name: 'h', path: '', version: '1.0.0', }, { alias: 'i', + isMissing: false, isPeer: false, + isSkipped: false, name: 'i', path: '', version: '1.0.0', }, { alias: 'k', + isMissing: false, isPeer: false, + isSkipped: false, name: 'k', path: '', version: '1.0.0', }, { alias: 'l', + isMissing: false, isPeer: false, + isSkipped: false, name: 'l', path: '', version: '1.0.0', @@ -617,7 +641,9 @@ test('sort list items', async (t) => { dependencies: [ { alias: 'foo', + isMissing: false, isPeer: false, + isSkipped: false, name: 'foo', path: '', version: '1.0.0', @@ -625,14 +651,18 @@ test('sort list items', async (t) => { dependencies: [ { alias: 'qar', + isMissing: false, isPeer: false, + isSkipped: false, name: 'qar', path: '', version: '1.0.0', }, { alias: 'bar', + isMissing: false, isPeer: false, + isSkipped: false, name: 'bar', path: '', version: '1.0.0', diff --git a/packages/pnpm/test/list.ts b/packages/pnpm/test/list.ts index b3449dc2c7..ea5a91f98e 100644 --- a/packages/pnpm/test/list.ts +++ b/packages/pnpm/test/list.ts @@ -224,3 +224,23 @@ test(`listing packages of a project that has an external ${WANTED_LOCKFILE}`, as is-positive 1.0.0 ` + '\n', 'prints all deps') }) + +test('list on a project with skipped optional dependencies', async (t: tape.Test) => { + prepare(t) + + await execPnpm('add', '--no-optional', 'pkg-with-optional') + + const result = execPnpmSync('list', '--depth', '10') + + t.equal(result.status, 0) + + t.equal(result.stdout.toString(), stripIndent` + Legend: production dependency, optional only, dev only + + project@0.0.0 /home/zoltan/src/pnpm/.tmp/1/project + + dependencies: + pkg-with-optional 1.0.0 + └── not-compatible-with-any-os 1.0.0 skipped + ` + '\n') +})