From a2d83ff75be6aef6937d15058d052151fba150e4 Mon Sep 17 00:00:00 2001 From: Simon Vocella Date: Mon, 24 Apr 2017 20:56:46 +0200 Subject: [PATCH] extract the reporter out of integrity checker --- src/cli/commands/check.js | 11 ++++- src/cli/commands/install.js | 2 +- src/integrity-checker.js | 94 ++++++++++++++++++------------------- 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/cli/commands/check.js b/src/cli/commands/check.js index c09593c750..d590d939e8 100644 --- a/src/cli/commands/check.js +++ b/src/cli/commands/check.js @@ -147,7 +147,15 @@ async function integrityHashCheck( reporter.error(reporter.lang(msg, ...vars)); errCount++; } - const integrityChecker = new InstallationIntegrityChecker(config, reporter); + const reasons = { + 'EXPECTED_MISSING': 'integrityFailedExpectedMissing', + 'FILES_MISSING': 'integrityFailedFilesMissing', + 'LOCKFILE_DONT_MATCH': 'integrityLockfilesDontMatch', + 'FLAGS_DONT_MATCH': 'integrityFlagsDontMatch', + 'PATTERNS_DONT_MATCH': 'integrityPatternsDontMatch', + 'LINKED_MODULES_DONT_MATCH': 'integrityCheckLinkedModulesDontMatch', + }; + const integrityChecker = new InstallationIntegrityChecker(config); const lockfile = await Lockfile.fromDirectory(config.cwd); const install = new Install(flags, config, reporter, lockfile); @@ -163,6 +171,7 @@ async function integrityHashCheck( reportError('noIntegrityFile'); } if (!match.integrityMatches) { + reportError(reasons[match.whyIntegrityMatchesFailed]); reportError('integrityCheckFailed'); } diff --git a/src/cli/commands/install.js b/src/cli/commands/install.js index a83fc819a7..e66619d6e8 100644 --- a/src/cli/commands/install.js +++ b/src/cli/commands/install.js @@ -172,7 +172,7 @@ export class Install { this.resolver = new PackageResolver(config, lockfile); this.fetcher = new PackageFetcher(config, this.resolver); - this.integrityChecker = new InstallationIntegrityChecker(config, this.reporter); + this.integrityChecker = new InstallationIntegrityChecker(config); this.compatibility = new PackageCompatibility(config, this.resolver, this.flags.ignoreEngines); this.linker = new PackageLinker(config, this.resolver); this.scripts = new PackageInstallScripts(config, this.resolver, this.flags.force); diff --git a/src/integrity-checker.js b/src/integrity-checker.js index 99abb24ac2..8189ece4f4 100644 --- a/src/integrity-checker.js +++ b/src/integrity-checker.js @@ -3,7 +3,6 @@ import type Config from './config.js'; import type {LockManifest} from './lockfile/wrapper.js'; import type {RegistryNames} from './registries/index.js'; -import type {Reporter} from './reporters/index.js'; import * as constants from './constants.js'; import {registryNames} from './registries/index.js'; import * as fs from './util/fs.js'; @@ -48,15 +47,11 @@ type IntegrityFlags = { export default class InstallationIntegrityChecker { constructor( config: Config, - reporter: Reporter, ) { this.config = config; - this.reporter = reporter; } config: Config; - reporter: Reporter; - /** * Get the location of an existing integrity hash. If none exists then return the location where we should @@ -168,32 +163,61 @@ export default class InstallationIntegrityChecker { return result; } - _compareIntegrityFiles(actual: IntegrityFile, expected: IntegrityFile): boolean { + async _getIntegrityFile(locationPath: string): Promise { + const expectedRaw = await fs.readFile(locationPath); + try { + return JSON.parse(expectedRaw); + } catch (e) { + // ignore JSON parsing for legacy text integrity files compatibility + } + return null; + } + + async _compareIntegrityFiles( + actual: IntegrityFile, + expected: ?IntegrityFile, + checkFiles: boolean, + locationFolder: string): Promise { + if (!expected) { + return Promise.resolve('EXPECTED_MISSING'); + } if (!compareSortedArrays(actual.linkedModules, expected.linkedModules)) { - this.reporter.warn(this.reporter.lang('integrityCheckLinkedModulesDontMatch')); - return false; + return Promise.resolve('LINKED_MODULES_DONT_MATCH'); } if (!compareSortedArrays(actual.topLevelPatters, expected.topLevelPatters)) { - this.reporter.warn(this.reporter.lang('integrityPatternsDontMatch')); - return false; + return Promise.resolve('PATTERNS_DONT_MATCH'); } if (!compareSortedArrays(actual.flags, expected.flags)) { - this.reporter.warn(this.reporter.lang('integrityFlagsDontMatch')); - return false; + return Promise.resolve('FLAGS_DONT_MATCH'); } for (const key of Object.keys(actual.lockfileEntries)) { if (actual.lockfileEntries[key] !== expected.lockfileEntries[key]) { - this.reporter.warn(this.reporter.lang('integrityLockfilesDontMatch')); - return false; + return Promise.resolve('LOCKFILE_DONT_MATCH'); } } for (const key of Object.keys(expected.lockfileEntries)) { if (actual.lockfileEntries[key] !== expected.lockfileEntries[key]) { - this.reporter.warn(this.reporter.lang('integrityLockfilesDontMatch')); - return false; + return Promise.resolve('LOCKFILE_DONT_MATCH'); + } + } + if (checkFiles) { + if (expected.files.length === 0) { + // edge case handling - --check-fies is passed but .yarn-integrity does not contain any files + // check and fail if there are file in node_modules after all. + const actualFiles = await this._getFilesDeep(locationFolder); + if (actualFiles.length > 0) { + return Promise.resolve('FILES_MISSING'); + } + } else { + // TODO we may want to optimise this check by checking only for package.json files on very large trees + for (const file of expected.files) { + if (!await fs.exists(path.join(locationFolder, file))) { + return Promise.resolve('FILES_MISSING'); + } + } } } - return true; + return Promise.resolve('OK'); } async check( @@ -215,41 +239,13 @@ export default class InstallationIntegrityChecker { patterns, Object.assign({}, {checkFiles: false}, flags), // don't generate files when checking, we check the files below loc.locationFolder); - const expectedRaw = await fs.readFile(loc.locationPath); - let expected: ?IntegrityFile; - try { - expected = JSON.parse(expectedRaw); - } catch (e) { - // ignore JSON parsing for legacy text integrity files compatibility - } - let integrityMatches; - if (expected) { - integrityMatches = this._compareIntegrityFiles(actual, expected); - if (flags.checkFiles && expected.files.length === 0) { - // edge case handling - --check-fies is passed but .yarn-integrity does not contain any files - // check and fail if there are file in node_modules after all. - const actualFiles = await this._getFilesDeep(loc.locationFolder); - if (actualFiles.length > 0) { - this.reporter.warn(this.reporter.lang('integrityFailedFilesMissing')); - integrityMatches = false; - } - } else if (flags.checkFiles && expected.files.length > 0) { - // TODO we may want to optimise this check by checking only for package.json files on very large trees - for (const file of expected.files) { - if (!await fs.exists(path.join(loc.locationFolder, file))) { - this.reporter.warn(this.reporter.lang('integrityFailedFilesMissing')); - integrityMatches = false; - break; - } - } - } - } else { - integrityMatches = false; - } + const expected = await this._getIntegrityFile(loc.locationPath); + const integrityMatches = await this._compareIntegrityFiles(actual, expected, flags.checkFiles, loc.locationFolder); return { integrityFileMissing: false, - integrityMatches, + integrityMatches: integrityMatches === 'OK', + whyIntegrityMatchesFailed: integrityMatches, missingPatterns, artifacts: expected ? expected.artifacts : null, };