From ec6e577387ccc0039d9bb0423e9745f20661280d Mon Sep 17 00:00:00 2001 From: zkochan Date: Thu, 22 Jun 2017 22:01:48 +0300 Subject: [PATCH] feat: add layoutVersion to .modules.yaml BREAKING CHANGE: The new layout is not compatible with previous versions. --- src/api/checkCompatibility.ts | 90 ++--------------------------------- src/api/install.ts | 6 ++- src/api/uninstall.ts | 4 +- src/fs/modulesController.ts | 3 ++ test/breakingChanges.ts | 14 ------ 5 files changed, 15 insertions(+), 102 deletions(-) diff --git a/src/api/checkCompatibility.ts b/src/api/checkCompatibility.ts index dc7bf104bf..61d5f63936 100644 --- a/src/api/checkCompatibility.ts +++ b/src/api/checkCompatibility.ts @@ -1,5 +1,5 @@ import {stripIndent, oneLine} from 'common-tags' -import {Modules} from '../fs/modulesController' +import {Modules, LAYOUT_VERSION} from '../fs/modulesController' import {PnpmError, PnpmErrorCode} from '../errorTypes' import semver = require('semver') @@ -41,24 +41,6 @@ class BreakingChangeError extends PnpmError { additionalInformation?: string } -type StoreBreakingChangeErrorOptions = ErrorRelatedSources & { - storePath: string, -} - -class StoreBreakingChangeError extends BreakingChangeError { - constructor (opts: StoreBreakingChangeErrorOptions) { - super({ - code: 'STORE_BREAKING_CHANGE', - message: `The store structure was changed. Try running the same command with the --force parameter.`, - additionalInformation: opts.additionalInformation, - relatedIssue: opts.relatedIssue, - relatedPR: opts.relatedPR, - }) - this.storePath = opts.storePath - } - storePath: string -} - type ModulesBreakingChangeErrorOptions = ErrorRelatedSources & { modulesPath: string, } @@ -90,75 +72,11 @@ export default function checkCompatibility ( actualStorePath: opts.storePath, }) } - if (!modules.packageManager) { + if (!modules.layoutVersion || modules.layoutVersion !== LAYOUT_VERSION) { throw new ModulesBreakingChangeError({ modulesPath: opts.modulesPath, - additionalInformation: 'The change was needed to allow machine stores and dependency locks', - relatedPR: 524, - }) - } - const pnpmVersion = getPackageManagerVersion(modules.packageManager) - check(pnpmVersion, opts.storePath, opts.modulesPath) -} - -function getPackageManagerVersion(packageManager: string) { - // handle the case when the package is scoped: @scope/pkgname - if (packageManager.startsWith('@')) { - return packageManager.split('@')[2] - } else { - return packageManager.split('@')[1] - } -} - -function check (pnpmVersion: string, storePath: string, modulesPath: string) { - if (!pnpmVersion || semver.lt(pnpmVersion, '0.28.0')) { - throw new StoreBreakingChangeError({ - storePath, - relatedIssue: 276, - }) - } - if (semver.lt(pnpmVersion, '0.33.0')) { - throw new StoreBreakingChangeError({ - storePath, - additionalInformation: 'The change was needed to fix the GitHub rate limit issue', - relatedIssue: 361, - relatedPR: 363, - }) - } - if (semver.lt(pnpmVersion, '0.37.0')) { - throw new StoreBreakingChangeError({ - storePath, - additionalInformation: 'The structure of store.json/dependencies was changed to map dependencies to their fullnames', - }) - } - if (semver.lt(pnpmVersion, '0.38.0')) { - throw new StoreBreakingChangeError({ - storePath, - additionalInformation: 'The structure of store.json/dependencies was changed to not include the redundunt package.json at the end', - }) - } - if (!pnpmVersion || semver.lt(pnpmVersion, '0.48.0')) { - throw new ModulesBreakingChangeError({ modulesPath, relatedPR: 534 }) - } - if (semver.lt(pnpmVersion, '0.51.0')) { - throw new ModulesBreakingChangeError({ modulesPath, relatedPR: 576 }) - } - if (semver.lt(pnpmVersion, '0.52.0')) { - throw new ModulesBreakingChangeError({ modulesPath, relatedPR: 593 }) - } - if (semver.lt(pnpmVersion, '0.62.0')) { - throw new ModulesBreakingChangeError({ - modulesPath, - relatedPR: 660, - additionalInformation: 'Information about the node_modules structure is stored in a node_modules/.shrinkwrap.yaml file instead of a node_modules/.graph.yaml file' - }) - } - if (semver.lt(pnpmVersion, '0.64.0')) { - throw new ModulesBreakingChangeError({ - modulesPath, - relatedPR: 694, - relatedIssue: 678, - additionalInformation: 'Packages having peer dependencies are linked to different variations. The variations depend on the set of resolved peer dependencies' + additionalInformation: 'The change was needed to make `independent-leafs` not the default installation layout', + relatedIssue: 821, }) } } diff --git a/src/api/install.ts b/src/api/install.ts index 1dd8638a4f..724b4948ef 100644 --- a/src/api/install.ts +++ b/src/api/install.ts @@ -27,7 +27,10 @@ import { ResolvedDependencies, } from 'pnpm-lockfile' import {pkgIdToRef} from '../fs/shrinkwrap' -import {save as saveModules} from '../fs/modulesController' +import { + save as saveModules, + LAYOUT_VERSION, +} from '../fs/modulesController' import mkdirp = require('mkdirp-promise') import createMemoize, {MemoizedFunc} from '../memoize' import {Package} from '../types' @@ -381,6 +384,7 @@ async function installInContext ( packageManager: `${pnpmPkgJson.name}@${pnpmPkgJson.version}`, storePath: ctx.storePath, skipped: Array.from(installCtx.skipped), + layoutVersion: LAYOUT_VERSION, }) // postinstall hooks diff --git a/src/api/uninstall.ts b/src/api/uninstall.ts index 037fd78d34..3d078d37e5 100644 --- a/src/api/uninstall.ts +++ b/src/api/uninstall.ts @@ -12,7 +12,8 @@ import { prune as pruneShrinkwrap, } from 'pnpm-lockfile' import { - save as saveModules + save as saveModules, + LAYOUT_VERSION, } from '../fs/modulesController' import removeOrphanPkgs from './removeOrphanPkgs' import {PackageSpec} from '../resolve' @@ -58,6 +59,7 @@ export async function uninstallInContext (pkgsToUninstall: string[], ctx: PnpmCo packageManager: `${pnpmPkgJson.name}@${pnpmPkgJson.version}`, storePath: ctx.storePath, skipped: Array.from(ctx.skipped).filter(pkgId => removedPkgIds.indexOf(pkgId) === -1), + layoutVersion: LAYOUT_VERSION, }) await removeOuterLinks(pkgsToUninstall, path.join(ctx.root, 'node_modules'), {storePath: ctx.storePath}) } diff --git a/src/fs/modulesController.ts b/src/fs/modulesController.ts index 96657bb897..43c8df9389 100644 --- a/src/fs/modulesController.ts +++ b/src/fs/modulesController.ts @@ -6,10 +6,13 @@ import writeYamlFile = require('write-yaml-file') // thinks that it is an extraneous package. const modulesFileName = '.modules.yaml' +export const LAYOUT_VERSION = 1 + export type Modules = { packageManager: string, storePath: string, skipped: string[], + layoutVersion: number, } export async function read (modulesPath: string): Promise { diff --git a/test/breakingChanges.ts b/test/breakingChanges.ts index 4359f15cc0..d1f299131d 100644 --- a/test/breakingChanges.ts +++ b/test/breakingChanges.ts @@ -50,20 +50,6 @@ test('fail on non-compatible node_modules when forced with a named installation' } }) -test('fail on non-compatible store', async t => { - const project = prepare(t) - const opts = testDefaults() - - await saveModulesYaml('0.32.0', path.join(opts.store, STORE_VERSION)) - - try { - await installPkgs(['is-negative'], opts) - t.fail('should have failed') - } catch (err) { - t.equal(err.code, 'STORE_BREAKING_CHANGE', 'store breaking change error is thrown') - } -}) - test("don't fail on non-compatible store when forced", async t => { const project = prepare(t) const opts = testDefaults({force: true})