From 7dfe6bef9b3d34fa2fdb87f99674bf3e4386a949 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Mon, 22 Oct 2018 14:02:02 +0200 Subject: [PATCH] Check package json version instead of zos version for dependencies --- .../cli/src/models/dependency/Dependency.js | 43 +++++++++++++++---- .../test/mocks/mock-stdlib/zos.invalid.json | 16 +++++++ packages/cli/test/models/Dependency.test.js | 10 ++++- packages/cli/test/scripts/link.test.js | 9 ++-- packages/cli/test/scripts/push.test.js | 3 +- 5 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 packages/cli/test/mocks/mock-stdlib/zos.invalid.json diff --git a/packages/cli/src/models/dependency/Dependency.js b/packages/cli/src/models/dependency/Dependency.js index 16f68b644..7eeea53d2 100644 --- a/packages/cli/src/models/dependency/Dependency.js +++ b/packages/cli/src/models/dependency/Dependency.js @@ -15,7 +15,9 @@ export default class Dependency { } static satisfiesVersion(version, requirement) { - return !requirement || version === requirement || semver.satisfies(version, requirement); + return !requirement + || version === requirement + || semver.satisfies(version, requirement); } static async install(nameAndVersion) { @@ -28,11 +30,17 @@ export default class Dependency { this.name = name this._networkFiles = {} - const packageVersion = this.getPackageFile().version - this._validateSatisfiesVersion(packageVersion, requirement) - this.version = packageVersion - this.nameAndVersion = `${name}@${packageVersion}` - this.requirement = requirement || tryWithCaret(packageVersion) + const zosVersion = this.getPackageFile().version + const npmVersion = this.getNpmFile().version + this._validateSatisfiesNpmVersion(npmVersion, requirement) + + this.version = npmVersion + this.npmRequirement = requirement || tryWithCaret(npmVersion) + this.zosRequirement = tryWithCaret(zosVersion) + } + + get requirement() { + return this.npmRequirement } async deploy(txParams) { @@ -64,6 +72,17 @@ export default class Dependency { return project } + getNpmFile() { + if (!this._npmFile) { + const filename = `node_modules/${this.name}/package.json` + if (!fs.exists(filename)) { + throw Error(`Could not find a package.json file for '${this.name}'.`) + } + this._npmFile = fs.parseJson(filename); + } + return this._npmFile + } + getPackageFile() { if (!this._packageFile) { const filename = `node_modules/${this.name}/zos.json` @@ -83,7 +102,7 @@ export default class Dependency { } this._networkFiles[network] = new ZosNetworkFile(this.getPackageFile(), network, filename) - this._validateSatisfiesVersion(this._networkFiles[network].version, this.requirement) + this._validateSatisfiesNetworkVersion(this._networkFiles[network].version, this.zosRequirement, network) } return this._networkFiles[network] } @@ -98,9 +117,15 @@ export default class Dependency { return `node_modules/${this.name}/zos.${network}.json` } - _validateSatisfiesVersion(version, requirement) { + _validateSatisfiesNpmVersion(version, requirement) { + if (!Dependency.satisfiesVersion(version, requirement)) { + throw Error(`Dependency ${this.name} requires package version ${requirement}, but ${version} was found. Please update ${this.name} package to the required version.`); + } + } + + _validateSatisfiesNetworkVersion(version, requirement, network) { if (!Dependency.satisfiesVersion(version, requirement)) { - throw Error(`Required dependency version ${requirement} does not match version ${version}`); + throw Error(`Dependency ${this.name} defines version ${semver.coerce(requirement)}, but ${version} was found for network ${network}.`); } } } diff --git a/packages/cli/test/mocks/mock-stdlib/zos.invalid.json b/packages/cli/test/mocks/mock-stdlib/zos.invalid.json new file mode 100644 index 000000000..4862b87d7 --- /dev/null +++ b/packages/cli/test/mocks/mock-stdlib/zos.invalid.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0", + "zosversion": "2", + "provider": { + "address": "0x0000000000000000000000000000000000000010" + }, + "package": { + "address": "0x0000000000000000000000000000000000000080" + }, + "contracts": { + "Greeter": { + "address": "0x1020", + "bytecodeHash": "0x0001" + } + } +} diff --git a/packages/cli/test/models/Dependency.test.js b/packages/cli/test/models/Dependency.test.js index 2213e0baf..d12d85c0f 100644 --- a/packages/cli/test/models/Dependency.test.js +++ b/packages/cli/test/models/Dependency.test.js @@ -54,7 +54,7 @@ contract('Dependency', function([_, from]) { describe('#constructor', function() { context('with invalid version', function() { it('throws an error',function() { - assertErrorMessage(() => new Dependency('mock-stdlib', '1.2.0'), /does not match version/) + assertErrorMessage(() => new Dependency('mock-stdlib', '1.2.0'), /requires package version 1\.2\.0/) }) }) @@ -115,11 +115,17 @@ contract('Dependency', function([_, from]) { }) context('for an existent network', function() { - it ('generates network file', function() { + it ('returns network file', function() { const networkFile = this.dependency.getNetworkFile('test') networkFile.fileName.should.eq('node_modules/mock-stdlib/zos.test.json') }) }) + + context('on a mismatching version', function() { + it('throws an error', function() { + assertErrorMessage(() => this.dependency.getNetworkFile('invalid'), /defines version 1\.1\.0/) + }) + }) }) }) diff --git a/packages/cli/test/scripts/link.test.js b/packages/cli/test/scripts/link.test.js index 123b94776..4cdaad067 100644 --- a/packages/cli/test/scripts/link.test.js +++ b/packages/cli/test/scripts/link.test.js @@ -56,9 +56,10 @@ contract('link script', function() { .should.be.rejectedWith('Package projects cannot use other packages.'); }); - it('should raise an error if requested version of dependency does not match its package version', async function () { - await linkLibs({ libs: ['mock-stdlib-invalid@1.0.0'], packageFile: this.packageFile }) - .should.be.rejectedWith('Required dependency version 1.0.0 does not match version 2.0.0') + it('should allow mismatching npm and zos versions', async function () { + // mock-stdlib-invalid has npm version 1.1.0 but zos version 2.0.0 + await linkLibs({ libs: ['mock-stdlib-invalid@1.1.0'], packageFile: this.packageFile }); + this.shouldHaveDependency('mock-stdlib', '1.1.0'); }); it('should install the dependency if a valid version range is requested', async function () { @@ -73,7 +74,7 @@ contract('link script', function() { it('should raise an error if requested version range does not match its package version', async function () { await linkLibs({ libs: ['mock-stdlib@~1.0.0'], packageFile: this.packageFile }) - .should.be.rejectedWith('Required dependency version ~1.0.0 does not match version 1.1.0') + .should.be.rejectedWith('mock-stdlib requires package version ~1.0.0, but 1.1.0 was found.') }); it('should raise an error if requested version of dependency lacks zosversion identifier', async function () { diff --git a/packages/cli/test/scripts/push.test.js b/packages/cli/test/scripts/push.test.js index 4f2790eb8..796b6e819 100644 --- a/packages/cli/test/scripts/push.test.js +++ b/packages/cli/test/scripts/push.test.js @@ -296,6 +296,7 @@ contract('push script', function([_, owner]) { const mockStdlibPackage = new ZosPackageFile('test/mocks/mock-stdlib/zos.json'); mockStdlibPackage.version = newVersion; sinon.stub(Dependency.prototype, 'getPackageFile').callsFake(() => mockStdlibPackage); + sinon.stub(Dependency.prototype, 'getNpmFile').callsFake(() => ({ version: '1.2.0' })); await this.dependencyPackage.newVersion(newVersion) this.dependencyGetNetworkFileStub.callsFake(() => ({ packageAddress: this.dependencyPackage.address, version: newVersion })); @@ -436,7 +437,7 @@ contract('push script', function([_, owner]) { it('should fail to push', async function () { await push({ network, txParams, networkFile: this.networkFile }) - .should.be.rejectedWith(/Required dependency version 1.0.0 does not match version 2.0.0/) + .should.be.rejectedWith(/requires package version 1.0.0, but 1.1.0 was found/) }); })