@pnpm/core
Version:
Fast, disk space efficient installation engine
143 lines • 6.66 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateModules = validateModules;
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const error_1 = require("@pnpm/error");
const logger_1 = require("@pnpm/logger");
const types_1 = require("@pnpm/types");
const rimraf_1 = __importDefault(require("@zkochan/rimraf"));
const enquirer_1 = __importDefault(require("enquirer"));
const equals_1 = __importDefault(require("ramda/src/equals"));
const index_js_1 = require("./checkCompatibility/index.js");
async function validateModules(modules, projects, opts) {
const rootProject = projects.find(({ id }) => id === '.');
if (opts.virtualStoreDirMaxLength !== modules.virtualStoreDirMaxLength) {
if (opts.forceNewModules && (rootProject != null)) {
await purgeModulesDirsOfImporter(opts, rootProject);
return { purged: true };
}
throw new error_1.PnpmError('VIRTUAL_STORE_DIR_MAX_LENGTH_DIFF', 'This modules directory was created using a different virtual-store-dir-max-length value.' +
' Run "pnpm install" to recreate the modules directory.');
}
if (opts.forcePublicHoistPattern &&
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
!(0, equals_1.default)(modules.publicHoistPattern, opts.publicHoistPattern || undefined)) {
if (opts.forceNewModules && (rootProject != null)) {
await purgeModulesDirsOfImporter(opts, rootProject);
return { purged: true };
}
throw new error_1.PnpmError('PUBLIC_HOIST_PATTERN_DIFF', 'This modules directory was created using a different public-hoist-pattern value.' +
' Run "pnpm install" to recreate the modules directory.');
}
const importersToPurge = [];
if (opts.forceHoistPattern && (rootProject != null)) {
try {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
if (!(0, equals_1.default)(opts.currentHoistPattern, opts.hoistPattern || undefined)) {
throw new error_1.PnpmError('HOIST_PATTERN_DIFF', 'This modules directory was created using a different hoist-pattern value.' +
' Run "pnpm install" to recreate the modules directory.');
}
}
catch (err) { // eslint-disable-line
if (!opts.forceNewModules)
throw err;
importersToPurge.push(rootProject);
}
}
for (const project of projects) {
try {
(0, index_js_1.checkCompatibility)(modules, {
modulesDir: project.modulesDir,
storeDir: opts.storeDir,
virtualStoreDir: opts.virtualStoreDir,
});
if (opts.lockfileDir !== project.rootDir && (opts.include != null) && modules.included) {
for (const depsField of types_1.DEPENDENCIES_FIELDS) {
if (opts.include[depsField] !== modules.included[depsField]) {
throw new error_1.PnpmError('INCLUDED_DEPS_CONFLICT', `modules directory (at "${opts.lockfileDir}") was installed with ${stringifyIncludedDeps(modules.included)}. ` +
`Current install wants ${stringifyIncludedDeps(opts.include)}.`);
}
}
}
}
catch (err) { // eslint-disable-line
if (!opts.forceNewModules)
throw err;
importersToPurge.push(project);
}
}
if (importersToPurge.length > 0 && (rootProject == null)) {
importersToPurge.push({
modulesDir: path_1.default.join(opts.lockfileDir, opts.modulesDir),
rootDir: opts.lockfileDir,
});
}
const purged = importersToPurge.length > 0;
if (purged) {
await purgeModulesDirsOfImporters(opts, importersToPurge);
}
return { purged };
}
async function purgeModulesDirsOfImporter(opts, importer) {
return purgeModulesDirsOfImporters(opts, [importer]);
}
async function purgeModulesDirsOfImporters(opts, importers) {
if (opts.confirmModulesPurge ?? true) {
if (!process.stdin.isTTY) {
throw new error_1.PnpmError('ABORTED_REMOVE_MODULES_DIR_NO_TTY', 'Aborted removal of modules directory due to no TTY', {
hint: 'If you are running pnpm in CI, set the CI environment variable to "true".',
});
}
const confirmed = await enquirer_1.default.prompt({
type: 'confirm',
name: 'question',
message: importers.length === 1
? `The modules directory at "${importers[0].modulesDir}" will be removed and reinstalled from scratch. Proceed?`
: 'The modules directories will be removed and reinstalled from scratch. Proceed?',
initial: true,
});
if (!confirmed.question) {
throw new error_1.PnpmError('ABORTED_REMOVE_MODULES_DIR', 'Aborted removal of modules directory');
}
}
await Promise.all(importers.map(async (importer) => {
logger_1.logger.info({
message: `Recreating ${importer.modulesDir}`,
prefix: importer.rootDir,
});
try {
// We don't remove the actual modules directory, just the contents of it.
// 1. we will need the directory anyway.
// 2. in some setups, pnpm won't even have permission to remove the modules directory.
await removeContentsOfDir(importer.modulesDir, opts.virtualStoreDir);
}
catch (err) { // eslint-disable-line
if (err.code !== 'ENOENT')
throw err;
}
}));
}
async function removeContentsOfDir(dir, virtualStoreDir) {
const items = await fs_1.promises.readdir(dir);
await Promise.all(items.map(async (item) => {
// The non-pnpm related hidden files are kept
if (item[0] === '.' &&
item !== '.bin' &&
item !== '.modules.yaml' &&
!dirsAreEqual(path_1.default.join(dir, item), virtualStoreDir)) {
return;
}
await (0, rimraf_1.default)(path_1.default.join(dir, item));
}));
}
function dirsAreEqual(dir1, dir2) {
return path_1.default.relative(dir1, dir2) === '';
}
function stringifyIncludedDeps(included) {
return types_1.DEPENDENCIES_FIELDS.filter((depsField) => included[depsField]).join(', ');
}
//# sourceMappingURL=validateModules.js.map