Skip to content

Commit

Permalink
extract the reporter out of integrity checker
Browse files Browse the repository at this point in the history
  • Loading branch information
voxsim committed Apr 24, 2017
1 parent 5fc8539 commit a2d83ff
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 51 deletions.
11 changes: 10 additions & 1 deletion src/cli/commands/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -163,6 +171,7 @@ async function integrityHashCheck(
reportError('noIntegrityFile');
}
if (!match.integrityMatches) {
reportError(reasons[match.whyIntegrityMatchesFailed]);
reportError('integrityCheckFailed');
}

Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
94 changes: 45 additions & 49 deletions src/integrity-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -168,32 +163,61 @@ export default class InstallationIntegrityChecker {
return result;
}

_compareIntegrityFiles(actual: IntegrityFile, expected: IntegrityFile): boolean {
async _getIntegrityFile(locationPath: string): Promise<?IntegrityFile> {
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<string> {
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(
Expand All @@ -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,
};
Expand Down

0 comments on commit a2d83ff

Please sign in to comment.