From d89934954d22e5175a7d97f407e2cd43a04d0b57 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 22:31:04 -0700 Subject: extract function getSolcAsync() --- packages/sol-compiler/src/compiler.ts | 43 ++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 3620a3ec1..5c99e3dae 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -53,6 +53,30 @@ const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { }; const CONFIG_FILE = 'compiler.json'; +async function getSolcAsync( + solcVersion: string, +): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + const fullSolcVersion = binPaths[solcVersion]; + const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); + let solcjs: string; + const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); + if (isCompilerAvailableLocally) { + solcjs = fs.readFileSync(compilerBinFilename).toString(); + } else { + logUtils.log(`Downloading ${fullSolcVersion}...`); + const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; + const response = await fetchAsync(url); + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { + throw new Error(`Failed to load ${fullSolcVersion}`); + } + solcjs = await response.text(); + fs.writeFileSync(compilerBinFilename, solcjs); + } + const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + return { solcInstance, fullSolcVersion }; +} + /** * The Compiler facilitates compiling Solidity smart contracts and saves the results * to artifact files. @@ -139,24 +163,7 @@ export class Compiler { const availableCompilerVersions = _.keys(binPaths); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); } - const fullSolcVersion = binPaths[solcVersion]; - const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); - let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); - } else { - logUtils.log(`Downloading ${fullSolcVersion}...`); - const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; - const response = await fetchAsync(url); - const SUCCESS_STATUS = 200; - if (response.status !== SUCCESS_STATUS) { - throw new Error(`Failed to load ${fullSolcVersion}`); - } - solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); - } - const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); const standardInput: solc.StandardInput = { -- cgit v1.2.3 From 478bf14289d1555753353b837e4efc63b2c776fe Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 22:48:14 -0700 Subject: extract method _compile() --- packages/sol-compiler/src/compiler.ts | 51 ++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 5c99e3dae..83caa2a19 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -175,30 +175,7 @@ export class Compiler { }, settings: this._compilerSettings, }; - const compiled: solc.StandardOutput = JSON.parse( - solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => { - const sourceCodeIfExists = this._resolver.resolve(importPath); - return { contents: sourceCodeIfExists.source }; - }), - ); - - if (!_.isUndefined(compiled.errors)) { - const SOLIDITY_WARNING = 'warning'; - const errors = _.filter(compiled.errors, entry => entry.severity !== SOLIDITY_WARNING); - const warnings = _.filter(compiled.errors, entry => entry.severity === SOLIDITY_WARNING); - if (!_.isEmpty(errors)) { - errors.forEach(error => { - const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); - logUtils.log(chalk.red(normalizedErrMsg)); - }); - process.exit(1); - } else { - warnings.forEach(warning => { - const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); - logUtils.log(chalk.yellow(normalizedWarningMsg)); - }); - } - } + const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput); const compiledData = compiled.contracts[contractSource.path][contractName]; if (_.isUndefined(compiledData)) { throw new Error( @@ -258,6 +235,32 @@ export class Compiler { await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); logUtils.log(`${contractName} artifact saved!`); } + private _compile(solcInstance: solc.SolcInstance, standardInput: solc.StandardInput): solc.StandardOutput { + const compiled: solc.StandardOutput = JSON.parse( + solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => { + const sourceCodeIfExists = this._resolver.resolve(importPath); + return { contents: sourceCodeIfExists.source }; + }), + ); + if (!_.isUndefined(compiled.errors)) { + const SOLIDITY_WARNING = 'warning'; + const errors = _.filter(compiled.errors, entry => entry.severity !== SOLIDITY_WARNING); + const warnings = _.filter(compiled.errors, entry => entry.severity === SOLIDITY_WARNING); + if (!_.isEmpty(errors)) { + errors.forEach(error => { + const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); + logUtils.log(chalk.red(normalizedErrMsg)); + }); + throw new Error("Compilation errors encountered"); + } else { + warnings.forEach(warning => { + const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); + logUtils.log(chalk.yellow(normalizedWarningMsg)); + }); + } + } + return compiled; + } /** * Gets the source tree hash for a file and its dependencies. * @param fileName Name of contract file. -- cgit v1.2.3 From 783bc873db04a9f712300e57a346ce803b85590c Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 23:09:07 -0700 Subject: extract method _verifyAndPersistCompilationAsync() --- packages/sol-compiler/src/compiler.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 83caa2a19..f301b697b 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -176,6 +176,23 @@ export class Compiler { settings: this._compilerSettings, }; const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput); + return this._verifyAndPersistCompilationAsync( + contractSource, + contractName, + fullSolcVersion, + compiled, + sourceTreeHashHex, + currentArtifactIfExists, + ); + } + private async _verifyAndPersistCompilationAsync( + contractSource: { path: string }, + contractName: string, + fullSolcVersion: string, + compiled: solc.StandardOutput, + sourceTreeHashHex: string, + currentArtifactIfExists: ContractArtifact | void, + ): Promise { const compiledData = compiled.contracts[contractSource.path][contractName]; if (_.isUndefined(compiledData)) { throw new Error( @@ -251,7 +268,7 @@ export class Compiler { const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); logUtils.log(chalk.red(normalizedErrMsg)); }); - throw new Error("Compilation errors encountered"); + throw new Error('Compilation errors encountered'); } else { warnings.forEach(warning => { const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); -- cgit v1.2.3 From 014d71d5ae4e6ec2f4841b5153d2116d3bbf25a6 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 23:27:52 -0700 Subject: compile contracts in batches one batch per compiler version needed. --- packages/sol-compiler/src/compiler.ts | 101 +++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 31 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index f301b697b..63154f917 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -131,31 +131,50 @@ export class Compiler { } else { contractNamesToCompile = this._specifiedContracts; } - for (const contractNameToCompile of contractNamesToCompile) { - await this._compileContractAsync(contractNameToCompile); - } + return this._compileContractsAsync(contractNamesToCompile); } /** * Compiles contract and saves artifact to artifactsDir. * @param fileName Name of contract with '.sol' extension. */ - private async _compileContractAsync(contractName: string): Promise { + private async _compileContractsAsync(contractNames: string[]): Promise { + const inputsByVersion: { + [solcVersion: string]: { + standardInput: solc.StandardInput; + contractsToCompile: string[]; + }; + } = {}; + + const contractData: { + [contractPath: string]: { + currentArtifactIfExists: ContractArtifact | void; + sourceTreeHashHex: string; + contractName: string; + }; + } = {}; + + for (const contractName of contractNames) { const contractSource = this._resolver.resolve(contractName); - const absoluteContractPath = path.join(this._contractsDir, contractSource.path); - const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, contractName); - const sourceTreeHashHex = `0x${this._getSourceTreeHash(absoluteContractPath).toString('hex')}`; + contractData[contractSource.path] = { + contractName, + currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), + sourceTreeHashHex: `0x${this._getSourceTreeHash( + path.join(this._contractsDir, contractSource.path), + ).toString('hex')}`, + }; let shouldCompile = false; - if (_.isUndefined(currentArtifactIfExists)) { + if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { shouldCompile = true; } else { - const currentArtifact = currentArtifactIfExists as ContractArtifact; + const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); - const didSourceChange = currentArtifact.sourceTreeHashHex !== sourceTreeHashHex; + const didSourceChange = + currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } if (!shouldCompile) { - return; + continue; } let solcVersion = this._solcVersionIfExists; if (_.isUndefined(solcVersion)) { @@ -163,27 +182,47 @@ export class Compiler { const availableCompilerVersions = _.keys(binPaths); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); } - const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); - - logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); - const standardInput: solc.StandardInput = { - language: 'Solidity', - sources: { - [contractSource.path]: { - content: contractSource.source, + if (_.isUndefined(inputsByVersion[solcVersion])) { + inputsByVersion[solcVersion] = { + standardInput: { + language: 'Solidity', + sources: {}, + settings: this._compilerSettings, }, - }, - settings: this._compilerSettings, - }; - const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput); - return this._verifyAndPersistCompilationAsync( - contractSource, - contractName, - fullSolcVersion, - compiled, - sourceTreeHashHex, - currentArtifactIfExists, - ); + contractsToCompile: [], + }; + } + inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source }; + inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); + } + + for (const solcVersion in inputsByVersion) { + if (!inputsByVersion.hasOwnProperty(solcVersion)) { + continue; + } + + const input = inputsByVersion[solcVersion]; + logUtils.log( + `Compiling ${input.contractsToCompile.length} contracts (${ + input.contractsToCompile + }) with Solidity v${solcVersion}...`, + ); + + const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); + + const compiled = this._compile(solcInstance, input.standardInput); + + for (const contractPath of input.contractsToCompile) { + await this._verifyAndPersistCompilationAsync( + { path: contractPath }, + contractData[contractPath].contractName, + fullSolcVersion, + compiled, + contractData[contractPath].sourceTreeHashHex, + contractData[contractPath].currentArtifactIfExists, + ); + } + } } private async _verifyAndPersistCompilationAsync( contractSource: { path: string }, -- cgit v1.2.3 From db6de490b21b6df8dd414c58657c3b48c39dd6d0 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 23:59:00 -0700 Subject: corrected whitespace (no functional changes) --- packages/sol-compiler/src/compiler.ts | 80 ++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 39 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 63154f917..897ace9b6 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -154,46 +154,48 @@ export class Compiler { } = {}; for (const contractName of contractNames) { - const contractSource = this._resolver.resolve(contractName); - contractData[contractSource.path] = { - contractName, - currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), - sourceTreeHashHex: `0x${this._getSourceTreeHash( - path.join(this._contractsDir, contractSource.path), - ).toString('hex')}`, - }; - let shouldCompile = false; - if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { - shouldCompile = true; - } else { - const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; - const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; - const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); - const didSourceChange = - currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; - shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; - } - if (!shouldCompile) { - continue; - } - let solcVersion = this._solcVersionIfExists; - if (_.isUndefined(solcVersion)) { - const solcVersionRange = parseSolidityVersionRange(contractSource.source); - const availableCompilerVersions = _.keys(binPaths); - solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); - } - if (_.isUndefined(inputsByVersion[solcVersion])) { - inputsByVersion[solcVersion] = { - standardInput: { - language: 'Solidity', - sources: {}, - settings: this._compilerSettings, - }, - contractsToCompile: [], + const contractSource = this._resolver.resolve(contractName); + contractData[contractSource.path] = { + contractName, + currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), + sourceTreeHashHex: `0x${this._getSourceTreeHash( + path.join(this._contractsDir, contractSource.path), + ).toString('hex')}`, }; - } - inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source }; - inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); + let shouldCompile = false; + if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { + shouldCompile = true; + } else { + const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; + const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; + const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); + const didSourceChange = + currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; + shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; + } + if (!shouldCompile) { + continue; + } + let solcVersion = this._solcVersionIfExists; + if (_.isUndefined(solcVersion)) { + const solcVersionRange = parseSolidityVersionRange(contractSource.source); + const availableCompilerVersions = _.keys(binPaths); + solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); + } + if (_.isUndefined(inputsByVersion[solcVersion])) { + inputsByVersion[solcVersion] = { + standardInput: { + language: 'Solidity', + sources: {}, + settings: this._compilerSettings, + }, + contractsToCompile: [], + }; + } + inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { + content: contractSource.source, + }; + inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); } for (const solcVersion in inputsByVersion) { -- cgit v1.2.3 From aa27346f93fafa5fdc9fca69c5604caca9278dfd Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 14 Aug 2018 10:43:31 -0700 Subject: simplify method parameter --- packages/sol-compiler/src/compiler.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 897ace9b6..3b46d7b46 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -216,7 +216,7 @@ export class Compiler { for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompilationAsync( - { path: contractPath }, + contractPath, contractData[contractPath].contractName, fullSolcVersion, compiled, @@ -227,19 +227,17 @@ export class Compiler { } } private async _verifyAndPersistCompilationAsync( - contractSource: { path: string }, + contractPath: string, contractName: string, fullSolcVersion: string, compiled: solc.StandardOutput, sourceTreeHashHex: string, currentArtifactIfExists: ContractArtifact | void, ): Promise { - const compiledData = compiled.contracts[contractSource.path][contractName]; + const compiledData = compiled.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( - `Contract ${contractName} not found in ${ - contractSource.path - }. Please make sure your contract has the same name as it's file name`, + `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, ); } if (!_.isUndefined(compiledData.evm)) { -- cgit v1.2.3 From e79c7632e6e82ecc53563da6d8727ce4475078c6 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 14 Aug 2018 10:52:31 -0700 Subject: simplify method interface --- packages/sol-compiler/src/compiler.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 3b46d7b46..cf12825c4 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -215,25 +215,29 @@ export class Compiler { const compiled = this._compile(solcInstance, input.standardInput); for (const contractPath of input.contractsToCompile) { - await this._verifyAndPersistCompilationAsync( + await this._verifyAndPersistCompiledContractAsync( contractPath, - contractData[contractPath].contractName, + contractData[contractPath], fullSolcVersion, compiled, - contractData[contractPath].sourceTreeHashHex, - contractData[contractPath].currentArtifactIfExists, ); } } } - private async _verifyAndPersistCompilationAsync( + private async _verifyAndPersistCompiledContractAsync( contractPath: string, - contractName: string, + contractMetadata: { + currentArtifactIfExists: ContractArtifact | void; + sourceTreeHashHex: string; + contractName: string; + }, fullSolcVersion: string, compiled: solc.StandardOutput, - sourceTreeHashHex: string, - currentArtifactIfExists: ContractArtifact | void, ): Promise { + const contractName = contractMetadata.contractName; + const sourceTreeHashHex = contractMetadata.sourceTreeHashHex; + const currentArtifactIfExists = contractMetadata.currentArtifactIfExists; + const compiledData = compiled.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( -- cgit v1.2.3 From bb4558e0be3aa9c182217e56cd2ff2f042d5473a Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 14 Aug 2018 17:40:31 -0700 Subject: test compiler --- packages/sol-compiler/src/utils/fs_wrapper.ts | 2 + packages/sol-compiler/test/compiler_test.ts | 86 +++++++++++++++++++--- .../test/fixtures/contracts/BadContractName.sol | 3 + .../test/fixtures/contracts/EmptyContract.sol | 3 + 4 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 packages/sol-compiler/test/fixtures/contracts/BadContractName.sol create mode 100644 packages/sol-compiler/test/fixtures/contracts/EmptyContract.sol (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/utils/fs_wrapper.ts b/packages/sol-compiler/src/utils/fs_wrapper.ts index cc7b06175..6e3547a76 100644 --- a/packages/sol-compiler/src/utils/fs_wrapper.ts +++ b/packages/sol-compiler/src/utils/fs_wrapper.ts @@ -10,4 +10,6 @@ export const fsWrapper = { doesPathExistSync: fs.existsSync, rmdirSync: fs.rmdirSync, removeFileAsync: promisify(fs.unlink), + statAsync: promisify(fs.stat), + appendFileAsync: promisify(fs.appendFile), }; diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index c9e141ee9..4a3b6e4a7 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -1,5 +1,7 @@ -import { DoneCallback } from '@0xproject/types'; +import { join } from 'path'; + import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; import 'mocha'; import { Compiler } from '../src/compiler'; @@ -9,29 +11,28 @@ import { CompilerOptions, ContractArtifact } from '../src/utils/types'; import { exchange_binary } from './fixtures/exchange_bin'; import { constants } from './util/constants'; +chai.use(chaiAsPromised); const expect = chai.expect; describe('#Compiler', function(): void { this.timeout(constants.timeoutMs); // tslint:disable-line:no-invalid-this const artifactsDir = `${__dirname}/fixtures/artifacts`; const contractsDir = `${__dirname}/fixtures/contracts`; - const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; const compilerOpts: CompilerOptions = { artifactsDir, contractsDir, contracts: constants.contracts, }; - const compiler = new Compiler(compilerOpts); - beforeEach((done: DoneCallback) => { - (async () => { - if (fsWrapper.doesPathExistSync(exchangeArtifactPath)) { - await fsWrapper.removeFileAsync(exchangeArtifactPath); - } - await compiler.compileAsync(); - done(); - })().catch(done); - }); it('should create an Exchange artifact with the correct unlinked binary', async () => { + compilerOpts.contracts = ['Exchange']; + + const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; + if (fsWrapper.doesPathExistSync(exchangeArtifactPath)) { + await fsWrapper.removeFileAsync(exchangeArtifactPath); + } + + await new Compiler(compilerOpts).compileAsync(); + const opts = { encoding: 'utf8', }; @@ -47,4 +48,65 @@ describe('#Compiler', function(): void { const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -metadataHexLength); expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata); }); + it("should throw when Whatever.sol doesn't contain a Whatever contract", async () => { + const contract = 'BadContractName'; + + const exchangeArtifactPath = `${artifactsDir}/${contract}.json`; + if (fsWrapper.doesPathExistSync(exchangeArtifactPath)) { + await fsWrapper.removeFileAsync(exchangeArtifactPath); + } + + compilerOpts.contracts = [contract]; + const compiler = new Compiler(compilerOpts); + + expect(compiler.compileAsync()).to.be.rejectedWith(Error); + }); + describe('after a successful compilation', () => { + const contract = 'Exchange'; + let artifactPath: string; + let timeCompiled: number; + beforeEach(async () => { + compilerOpts.contracts = [contract]; + + artifactPath = `${artifactsDir}/${contract}.json`; + if (fsWrapper.doesPathExistSync(artifactPath)) { + await fsWrapper.removeFileAsync(artifactPath); + } + + await new Compiler(compilerOpts).compileAsync(); + + timeCompiled = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + }); + it('recompilation should update artifact when source has changed', async () => { + fsWrapper.appendFileAsync(join(contractsDir, `${contract}.sol`), ' '); + + await new Compiler(compilerOpts).compileAsync(); + + const timeRecompiled = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + + expect(timeRecompiled).to.not.equal(timeCompiled); + }); + it("recompilation should NOT update artifact when source hasn't changed", async () => { + await new Compiler(compilerOpts).compileAsync(); + + const timeRecompiled = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + + expect(timeRecompiled).to.equal(timeCompiled); + }); + }); + it('should only compile what was requested', async () => { + // remove all artifacts + for (const artifact of await fsWrapper.readdirAsync(artifactsDir)) { + await fsWrapper.removeFileAsync(join(artifactsDir, artifact)); + } + + // compile EmptyContract + compilerOpts.contracts = ['EmptyContract']; + await new Compiler(compilerOpts).compileAsync(); + + // make sure the artifacts dir only contains EmptyContract.json + for (const artifact of await fsWrapper.readdirAsync(artifactsDir)) { + expect(artifact).to.equal('EmptyContract.json'); + } + }); }); diff --git a/packages/sol-compiler/test/fixtures/contracts/BadContractName.sol b/packages/sol-compiler/test/fixtures/contracts/BadContractName.sol new file mode 100644 index 000000000..3193cc0eb --- /dev/null +++ b/packages/sol-compiler/test/fixtures/contracts/BadContractName.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.4.14; + +contract ContractNameThatDoesntMatchFilename { } diff --git a/packages/sol-compiler/test/fixtures/contracts/EmptyContract.sol b/packages/sol-compiler/test/fixtures/contracts/EmptyContract.sol new file mode 100644 index 000000000..971ca7826 --- /dev/null +++ b/packages/sol-compiler/test/fixtures/contracts/EmptyContract.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.4.14; + +contract EmptyContract { } -- cgit v1.2.3 From c11d8054695c84a4ff3d76730813c692e0a16dc3 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 14 Aug 2018 18:02:39 -0700 Subject: Update changelog --- packages/sol-compiler/CHANGELOG.json | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/CHANGELOG.json b/packages/sol-compiler/CHANGELOG.json index a351839a4..34326e434 100644 --- a/packages/sol-compiler/CHANGELOG.json +++ b/packages/sol-compiler/CHANGELOG.json @@ -1,4 +1,14 @@ [ + { + "version": "1.1.0", + "changes": [ + { + "note": + "Quicken compilation by sending multiple contracts to the same solcjs invocation, batching them together based on compiler version requirements.", + "pr": 965 + } + ] + }, { "timestamp": 1534210131, "version": "1.0.5", -- cgit v1.2.3 From c01810f0d755bdb3fa7b4b224a5a0d0493cd38a7 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:13:09 -0700 Subject: move getSolcAsync to static private method --- packages/sol-compiler/src/compiler.ts | 49 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index cf12825c4..c62a4c0ca 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -53,30 +53,6 @@ const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { }; const CONFIG_FILE = 'compiler.json'; -async function getSolcAsync( - solcVersion: string, -): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { - const fullSolcVersion = binPaths[solcVersion]; - const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); - let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); - } else { - logUtils.log(`Downloading ${fullSolcVersion}...`); - const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; - const response = await fetchAsync(url); - const SUCCESS_STATUS = 200; - if (response.status !== SUCCESS_STATUS) { - throw new Error(`Failed to load ${fullSolcVersion}`); - } - solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); - } - const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); - return { solcInstance, fullSolcVersion }; -} - /** * The Compiler facilitates compiling Solidity smart contracts and saves the results * to artifact files. @@ -210,7 +186,7 @@ export class Compiler { }) with Solidity v${solcVersion}...`, ); - const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); + const { solcInstance, fullSolcVersion } = await Compiler._getSolcAsync(solcVersion); const compiled = this._compile(solcInstance, input.standardInput); @@ -224,6 +200,29 @@ export class Compiler { } } } + private static async _getSolcAsync( + solcVersion: string, + ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + const fullSolcVersion = binPaths[solcVersion]; + const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); + let solcjs: string; + const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); + if (isCompilerAvailableLocally) { + solcjs = fs.readFileSync(compilerBinFilename).toString(); + } else { + logUtils.log(`Downloading ${fullSolcVersion}...`); + const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; + const response = await fetchAsync(url); + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { + throw new Error(`Failed to load ${fullSolcVersion}`); + } + solcjs = await response.text(); + fs.writeFileSync(compilerBinFilename, solcjs); + } + const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + return { solcInstance, fullSolcVersion }; + } private async _verifyAndPersistCompiledContractAsync( contractPath: string, contractMetadata: { -- cgit v1.2.3 From d744468479bf88c89412115860e0b8c4cf2a48c1 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:21:46 -0700 Subject: rename variable inputsByVersion to versionToInputs --- packages/sol-compiler/src/compiler.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index c62a4c0ca..0de8b8cad 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -114,7 +114,7 @@ export class Compiler { * @param fileName Name of contract with '.sol' extension. */ private async _compileContractsAsync(contractNames: string[]): Promise { - const inputsByVersion: { + const versionToInputs: { [solcVersion: string]: { standardInput: solc.StandardInput; contractsToCompile: string[]; @@ -158,8 +158,8 @@ export class Compiler { const availableCompilerVersions = _.keys(binPaths); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); } - if (_.isUndefined(inputsByVersion[solcVersion])) { - inputsByVersion[solcVersion] = { + if (_.isUndefined(versionToInputs[solcVersion])) { + versionToInputs[solcVersion] = { standardInput: { language: 'Solidity', sources: {}, @@ -168,18 +168,18 @@ export class Compiler { contractsToCompile: [], }; } - inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { + versionToInputs[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source, }; - inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); + versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - for (const solcVersion in inputsByVersion) { - if (!inputsByVersion.hasOwnProperty(solcVersion)) { + for (const solcVersion in versionToInputs) { + if (!versionToInputs.hasOwnProperty(solcVersion)) { continue; } - const input = inputsByVersion[solcVersion]; + const input = versionToInputs[solcVersion]; logUtils.log( `Compiling ${input.contractsToCompile.length} contracts (${ input.contractsToCompile -- cgit v1.2.3 From f0f94f199eff982ffa03c6a760235ed22a8ad68a Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:13:09 -0700 Subject: move getSolcAsync to static private method --- packages/sol-compiler/src/compiler.ts | 46 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 0de8b8cad..c162d65f4 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -65,6 +65,29 @@ export class Compiler { private readonly _artifactsDir: string; private readonly _solcVersionIfExists: string | undefined; private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; + private static async _getSolcAsync( + solcVersion: string, + ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + const fullSolcVersion = binPaths[solcVersion]; + const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); + let solcjs: string; + const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); + if (isCompilerAvailableLocally) { + solcjs = fs.readFileSync(compilerBinFilename).toString(); + } else { + logUtils.log(`Downloading ${fullSolcVersion}...`); + const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; + const response = await fetchAsync(url); + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { + throw new Error(`Failed to load ${fullSolcVersion}`); + } + solcjs = await response.text(); + fs.writeFileSync(compilerBinFilename, solcjs); + } + const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + return { solcInstance, fullSolcVersion }; + } /** * Instantiates a new instance of the Compiler class. * @return An instance of the Compiler class. @@ -200,29 +223,6 @@ export class Compiler { } } } - private static async _getSolcAsync( - solcVersion: string, - ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { - const fullSolcVersion = binPaths[solcVersion]; - const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); - let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); - } else { - logUtils.log(`Downloading ${fullSolcVersion}...`); - const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; - const response = await fetchAsync(url); - const SUCCESS_STATUS = 200; - if (response.status !== SUCCESS_STATUS) { - throw new Error(`Failed to load ${fullSolcVersion}`); - } - solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); - } - const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); - return { solcInstance, fullSolcVersion }; - } private async _verifyAndPersistCompiledContractAsync( contractPath: string, contractMetadata: { -- cgit v1.2.3 From 558286467bc7c05ea1a97a1fdfde0ad1ba7e279f Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:46:23 -0700 Subject: extract interfaces for re-used complex data types --- packages/sol-compiler/src/compiler.ts | 51 +++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index c162d65f4..286f15073 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -53,6 +53,23 @@ const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { }; const CONFIG_FILE = 'compiler.json'; +interface VersionToInputs { + [solcVersion: string]: { + standardInput: solc.StandardInput; + contractsToCompile: string[]; + }; +} + +interface ContractPathToData { + [contractPath: string]: ContractData; +} + +interface ContractData { + currentArtifactIfExists: ContractArtifact | void; + sourceTreeHashHex: string; + contractName: string; +} + /** * The Compiler facilitates compiling Solidity smart contracts and saves the results * to artifact files. @@ -137,24 +154,15 @@ export class Compiler { * @param fileName Name of contract with '.sol' extension. */ private async _compileContractsAsync(contractNames: string[]): Promise { - const versionToInputs: { - [solcVersion: string]: { - standardInput: solc.StandardInput; - contractsToCompile: string[]; - }; - } = {}; + // batch input contracts together based on the version of the compiler that they require. + const versionToInputs: VersionToInputs = {}; - const contractData: { - [contractPath: string]: { - currentArtifactIfExists: ContractArtifact | void; - sourceTreeHashHex: string; - contractName: string; - }; - } = {}; + // map contract paths to data about them for later verification and persistence + const contractPathToData: ContractPathToData = {}; for (const contractName of contractNames) { const contractSource = this._resolver.resolve(contractName); - contractData[contractSource.path] = { + contractPathToData[contractSource.path] = { contractName, currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), sourceTreeHashHex: `0x${this._getSourceTreeHash( @@ -162,14 +170,15 @@ export class Compiler { ).toString('hex')}`, }; let shouldCompile = false; - if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { + if (_.isUndefined(contractPathToData[contractSource.path].currentArtifactIfExists)) { shouldCompile = true; } else { - const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; + const currentArtifact = contractPathToData[contractSource.path] + .currentArtifactIfExists as ContractArtifact; const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); const didSourceChange = - currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; + currentArtifact.sourceTreeHashHex !== contractPathToData[contractSource.path].sourceTreeHashHex; shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } if (!shouldCompile) { @@ -216,7 +225,7 @@ export class Compiler { for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompiledContractAsync( contractPath, - contractData[contractPath], + contractPathToData[contractPath], fullSolcVersion, compiled, ); @@ -225,11 +234,7 @@ export class Compiler { } private async _verifyAndPersistCompiledContractAsync( contractPath: string, - contractMetadata: { - currentArtifactIfExists: ContractArtifact | void; - sourceTreeHashHex: string; - contractName: string; - }, + contractMetadata: ContractData, fullSolcVersion: string, compiled: solc.StandardOutput, ): Promise { -- cgit v1.2.3 From ad9a7d72ced3898d7ba2922433bc666980f81b4e Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:58:10 -0700 Subject: remedy missing *IfExists identifier suffix --- packages/sol-compiler/src/compiler.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 286f15073..1c08cb324 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -184,12 +184,9 @@ export class Compiler { if (!shouldCompile) { continue; } - let solcVersion = this._solcVersionIfExists; - if (_.isUndefined(solcVersion)) { - const solcVersionRange = parseSolidityVersionRange(contractSource.source); - const availableCompilerVersions = _.keys(binPaths); - solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); - } + const solcVersion = _.isUndefined(this._solcVersionIfExists) + ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) + : this._solcVersionIfExists; if (_.isUndefined(versionToInputs[solcVersion])) { versionToInputs[solcVersion] = { standardInput: { -- cgit v1.2.3 From 7c96fa45f85906a9ba4d09b8aaa4759e7d55286f Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 12:50:20 -0700 Subject: comments --- packages/sol-compiler/src/compiler.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 1c08cb324..ff3805073 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -188,6 +188,8 @@ export class Compiler { ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) : this._solcVersionIfExists; if (_.isUndefined(versionToInputs[solcVersion])) { + // no inputs batched yet for this version. + // prepare object to hold this batch. versionToInputs[solcVersion] = { standardInput: { language: 'Solidity', @@ -197,6 +199,7 @@ export class Compiler { contractsToCompile: [], }; } + // add input to the right version batch versionToInputs[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source, }; -- cgit v1.2.3 From 8959b0993e92d86fdf8539d11d4e4c70185eb8ed Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 13:38:41 -0700 Subject: raise error for unknown compiler version --- packages/sol-compiler/src/compiler.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index ff3805073..9a6dcff09 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -85,6 +85,9 @@ export class Compiler { private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + if (_.isUndefined(binPaths[solcVersion])) { + throw new Error(`${solcVersion} is not a known compiler version`); + } const fullSolcVersion = binPaths[solcVersion]; const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; -- cgit v1.2.3 From ec41e314b09ed348e1d268b1d896dbde275deb1b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 13:39:33 -0700 Subject: use `for...of _.keys` instead of `for...in` --- packages/sol-compiler/src/compiler.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 9a6dcff09..a676423cb 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -209,11 +209,7 @@ export class Compiler { versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - for (const solcVersion in versionToInputs) { - if (!versionToInputs.hasOwnProperty(solcVersion)) { - continue; - } - + for (const solcVersion of _.keys(versionToInputs)) { const input = versionToInputs[solcVersion]; logUtils.log( `Compiling ${input.contractsToCompile.length} contracts (${ -- cgit v1.2.3 From 455c78dfb1ee5a104964b70d0132438b86f6c437 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 14:09:57 -0700 Subject: renamed variable `compiled` to `compilerOutput` --- packages/sol-compiler/src/compiler.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index a676423cb..f0cb2ded3 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -219,14 +219,14 @@ export class Compiler { const { solcInstance, fullSolcVersion } = await Compiler._getSolcAsync(solcVersion); - const compiled = this._compile(solcInstance, input.standardInput); + const compilerOutput = this._compile(solcInstance, input.standardInput); for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompiledContractAsync( contractPath, contractPathToData[contractPath], fullSolcVersion, - compiled, + compilerOutput, ); } } @@ -235,13 +235,13 @@ export class Compiler { contractPath: string, contractMetadata: ContractData, fullSolcVersion: string, - compiled: solc.StandardOutput, + compilerOutput: solc.StandardOutput, ): Promise { const contractName = contractMetadata.contractName; const sourceTreeHashHex = contractMetadata.sourceTreeHashHex; const currentArtifactIfExists = contractMetadata.currentArtifactIfExists; - const compiledData = compiled.contracts[contractPath][contractName]; + const compiledData = compilerOutput.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, @@ -262,12 +262,12 @@ export class Compiler { } const sourceCodes = _.mapValues( - compiled.sources, + compilerOutput.sources, (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source, ); const contractVersion: ContractVersionData = { compilerOutput: compiledData, - sources: compiled.sources, + sources: compilerOutput.sources, sourceCodes, sourceTreeHashHex, compiler: { -- cgit v1.2.3 From 976d159e5275fa1fc0236fdd65c3acf40864657b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 15:20:00 -0700 Subject: follow chai_setup pattern --- packages/sol-compiler/package.json | 1 + packages/sol-compiler/test/compiler_test.ts | 4 ++-- packages/sol-compiler/test/util/chai_setup.ts | 13 +++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 packages/sol-compiler/test/util/chai_setup.ts (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index 7cb07e970..cdc641044 100644 --- a/packages/sol-compiler/package.json +++ b/packages/sol-compiler/package.json @@ -61,6 +61,7 @@ "@types/semver": "^5.5.0", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", + "chai-bignumber": "^2.0.2", "copyfiles": "^1.2.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index 4a3b6e4a7..4be77c01b 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -1,7 +1,6 @@ import { join } from 'path'; import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; import 'mocha'; import { Compiler } from '../src/compiler'; @@ -9,9 +8,10 @@ import { fsWrapper } from '../src/utils/fs_wrapper'; import { CompilerOptions, ContractArtifact } from '../src/utils/types'; import { exchange_binary } from './fixtures/exchange_bin'; +import { chaiSetup } from './util/chai_setup'; import { constants } from './util/constants'; -chai.use(chaiAsPromised); +chaiSetup.configure(); const expect = chai.expect; describe('#Compiler', function(): void { diff --git a/packages/sol-compiler/test/util/chai_setup.ts b/packages/sol-compiler/test/util/chai_setup.ts new file mode 100644 index 000000000..1a8733093 --- /dev/null +++ b/packages/sol-compiler/test/util/chai_setup.ts @@ -0,0 +1,13 @@ +import * as chai from 'chai'; +import chaiAsPromised = require('chai-as-promised'); +import ChaiBigNumber = require('chai-bignumber'); +import * as dirtyChai from 'dirty-chai'; + +export const chaiSetup = { + configure(): void { + chai.config.includeStack = true; + chai.use(ChaiBigNumber()); + chai.use(dirtyChai); + chai.use(chaiAsPromised); + }, +}; -- cgit v1.2.3 From 20ac6936ac19b141723cc88f03acfeeb79b89958 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 16:01:04 -0700 Subject: change .rejectedWith(error) to .rejected() --- packages/sol-compiler/test/compiler_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index 4be77c01b..08799c14b 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -59,7 +59,7 @@ describe('#Compiler', function(): void { compilerOpts.contracts = [contract]; const compiler = new Compiler(compilerOpts); - expect(compiler.compileAsync()).to.be.rejectedWith(Error); + expect(compiler.compileAsync()).to.be.rejected(); }); describe('after a successful compilation', () => { const contract = 'Exchange'; -- cgit v1.2.3 From 89202b7bdffe084511971e331f81dd5878f2a56c Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 16:01:57 -0700 Subject: clarify recompilation tests --- packages/sol-compiler/test/compiler_test.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index 08799c14b..7e22ff0ef 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -64,7 +64,7 @@ describe('#Compiler', function(): void { describe('after a successful compilation', () => { const contract = 'Exchange'; let artifactPath: string; - let timeCompiled: number; + let compilationTimestamp: number; beforeEach(async () => { compilerOpts.contracts = [contract]; @@ -75,23 +75,25 @@ describe('#Compiler', function(): void { await new Compiler(compilerOpts).compileAsync(); - timeCompiled = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + compilationTimestamp = (await fsWrapper.statAsync(artifactPath)).mtimeMs; }); it('recompilation should update artifact when source has changed', async () => { + // append some meaningless data to the contract, so that its hash + // will change, so that the compiler will decide to recompile it. fsWrapper.appendFileAsync(join(contractsDir, `${contract}.sol`), ' '); await new Compiler(compilerOpts).compileAsync(); - const timeRecompiled = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + const recompilationTimestamp = (await fsWrapper.statAsync(artifactPath)).mtimeMs; - expect(timeRecompiled).to.not.equal(timeCompiled); + expect(recompilationTimestamp).to.be.greaterThan(compilationTimestamp); }); it("recompilation should NOT update artifact when source hasn't changed", async () => { await new Compiler(compilerOpts).compileAsync(); - const timeRecompiled = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + const recompilationTimestamp = (await fsWrapper.statAsync(artifactPath)).mtimeMs; - expect(timeRecompiled).to.equal(timeCompiled); + expect(recompilationTimestamp).to.equal(compilationTimestamp); }); }); it('should only compile what was requested', async () => { -- cgit v1.2.3 From badcb35525a4ccd5c80b7ad79288b267b961faef Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 16:14:36 -0700 Subject: extract method _shouldCompile() --- packages/sol-compiler/src/compiler.ts | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index f0cb2ded3..390c2412a 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -172,19 +172,7 @@ export class Compiler { path.join(this._contractsDir, contractSource.path), ).toString('hex')}`, }; - let shouldCompile = false; - if (_.isUndefined(contractPathToData[contractSource.path].currentArtifactIfExists)) { - shouldCompile = true; - } else { - const currentArtifact = contractPathToData[contractSource.path] - .currentArtifactIfExists as ContractArtifact; - const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; - const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); - const didSourceChange = - currentArtifact.sourceTreeHashHex !== contractPathToData[contractSource.path].sourceTreeHashHex; - shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; - } - if (!shouldCompile) { + if (!this._shouldCompile(contractPathToData[contractSource.path])) { continue; } const solcVersion = _.isUndefined(this._solcVersionIfExists) @@ -231,6 +219,17 @@ export class Compiler { } } } + private _shouldCompile(contractData: ContractData): boolean { + if (_.isUndefined(contractData.currentArtifactIfExists)) { + return true; + } else { + const currentArtifact = contractData.currentArtifactIfExists as ContractArtifact; + const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; + const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); + const didSourceChange = currentArtifact.sourceTreeHashHex !== contractData.sourceTreeHashHex; + return !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; + } + } private async _verifyAndPersistCompiledContractAsync( contractPath: string, contractMetadata: ContractData, -- cgit v1.2.3 From 6b6b368bf6b3d9c6f69d47a2f304919c7e1c6ae1 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:29:36 -0700 Subject: consolidate binPaths... ref's into fullSolcVersion --- packages/sol-compiler/src/compiler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 390c2412a..1af11dcd0 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -85,10 +85,10 @@ export class Compiler { private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { - if (_.isUndefined(binPaths[solcVersion])) { + const fullSolcVersion = binPaths[solcVersion]; + if (_.isUndefined(fullSolcVersion)) { throw new Error(`${solcVersion} is not a known compiler version`); } - const fullSolcVersion = binPaths[solcVersion]; const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); -- cgit v1.2.3 From 11231795cd73c24fe1d4e2d5ee826e46271b8a62 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:32:27 -0700 Subject: change `return Promise` to `await...` --- packages/sol-compiler/src/compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 1af11dcd0..eb9670b03 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -150,7 +150,7 @@ export class Compiler { } else { contractNamesToCompile = this._specifiedContracts; } - return this._compileContractsAsync(contractNamesToCompile); + await this._compileContractsAsync(contractNamesToCompile); } /** * Compiles contract and saves artifact to artifactsDir. -- cgit v1.2.3 From acb3c0d0aa065edf1c71970467d038d52096e865 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:36:12 -0700 Subject: declare contractData before adding to map --- packages/sol-compiler/src/compiler.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index eb9670b03..bd7f751df 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -165,16 +165,17 @@ export class Compiler { for (const contractName of contractNames) { const contractSource = this._resolver.resolve(contractName); - contractPathToData[contractSource.path] = { + const contractData = { contractName, currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), sourceTreeHashHex: `0x${this._getSourceTreeHash( path.join(this._contractsDir, contractSource.path), ).toString('hex')}`, }; - if (!this._shouldCompile(contractPathToData[contractSource.path])) { + if (!this._shouldCompile(contractData)) { continue; } + contractPathToData[contractSource.path] = contractData; const solcVersion = _.isUndefined(this._solcVersionIfExists) ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) : this._solcVersionIfExists; -- cgit v1.2.3 From 421a7394dfcbc714b35ada8f8d8a9945b989d3c7 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:47:33 -0700 Subject: scrap comments in favor of self-documentation --- packages/sol-compiler/src/compiler.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index bd7f751df..713d8abe8 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -179,9 +179,8 @@ export class Compiler { const solcVersion = _.isUndefined(this._solcVersionIfExists) ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) : this._solcVersionIfExists; - if (_.isUndefined(versionToInputs[solcVersion])) { - // no inputs batched yet for this version. - // prepare object to hold this batch. + const isFirstContractWithThisVersion = _.isUndefined(versionToInputs[solcVersion]); + if (isFirstContractWithThisVersion) { versionToInputs[solcVersion] = { standardInput: { language: 'Solidity', -- cgit v1.2.3 From a607a61bde1677833a04765b8691184c49b04213 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:48:33 -0700 Subject: clarify iteration range --- packages/sol-compiler/src/compiler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 713d8abe8..bb870e0cf 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -197,7 +197,8 @@ export class Compiler { versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - for (const solcVersion of _.keys(versionToInputs)) { + const solcVersions = _.keys(versionToInputs); + for (const solcVersion of solcVersions) { const input = versionToInputs[solcVersion]; logUtils.log( `Compiling ${input.contractsToCompile.length} contracts (${ -- cgit v1.2.3 From a59f18927dc8f59bb69d7dff9d0e5cd7e148129b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:57:31 -0700 Subject: flatten out interface to verifyAndPersist* method --- packages/sol-compiler/src/compiler.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index bb870e0cf..296411b76 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -213,7 +213,9 @@ export class Compiler { for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompiledContractAsync( contractPath, - contractPathToData[contractPath], + contractPathToData[contractPath].currentArtifactIfExists, + contractPathToData[contractPath].sourceTreeHashHex, + contractPathToData[contractPath].contractName, fullSolcVersion, compilerOutput, ); @@ -233,14 +235,12 @@ export class Compiler { } private async _verifyAndPersistCompiledContractAsync( contractPath: string, - contractMetadata: ContractData, + currentArtifactIfExists: ContractArtifact | void, + sourceTreeHashHex: string, + contractName: string, fullSolcVersion: string, compilerOutput: solc.StandardOutput, ): Promise { - const contractName = contractMetadata.contractName; - const sourceTreeHashHex = contractMetadata.sourceTreeHashHex; - const currentArtifactIfExists = contractMetadata.currentArtifactIfExists; - const compiledData = compilerOutput.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( -- cgit v1.2.3 From 85427a84df9954c5849ea471f549549bc1486aec Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 11:17:57 -0700 Subject: clarify variable names for artifact mod times --- packages/sol-compiler/test/compiler_test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index 7e22ff0ef..003d863e7 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -64,7 +64,7 @@ describe('#Compiler', function(): void { describe('after a successful compilation', () => { const contract = 'Exchange'; let artifactPath: string; - let compilationTimestamp: number; + let artifactCreatedAtMs: number; beforeEach(async () => { compilerOpts.contracts = [contract]; @@ -75,7 +75,7 @@ describe('#Compiler', function(): void { await new Compiler(compilerOpts).compileAsync(); - compilationTimestamp = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + artifactCreatedAtMs = (await fsWrapper.statAsync(artifactPath)).mtimeMs; }); it('recompilation should update artifact when source has changed', async () => { // append some meaningless data to the contract, so that its hash @@ -84,16 +84,16 @@ describe('#Compiler', function(): void { await new Compiler(compilerOpts).compileAsync(); - const recompilationTimestamp = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + const artifactModifiedAtMs = (await fsWrapper.statAsync(artifactPath)).mtimeMs; - expect(recompilationTimestamp).to.be.greaterThan(compilationTimestamp); + expect(artifactModifiedAtMs).to.be.greaterThan(artifactCreatedAtMs); }); it("recompilation should NOT update artifact when source hasn't changed", async () => { await new Compiler(compilerOpts).compileAsync(); - const recompilationTimestamp = (await fsWrapper.statAsync(artifactPath)).mtimeMs; + const artifactModifiedAtMs = (await fsWrapper.statAsync(artifactPath)).mtimeMs; - expect(recompilationTimestamp).to.equal(compilationTimestamp); + expect(artifactModifiedAtMs).to.equal(artifactCreatedAtMs); }); }); it('should only compile what was requested', async () => { -- cgit v1.2.3 From 402ca27fbf91f543addf0d4618e071ae10cfd70e Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 13:59:46 -0700 Subject: change some *Sync to *Async --- packages/sol-compiler/src/compiler.ts | 22 ++++++++++++++++++---- packages/sol-compiler/src/utils/fs_wrapper.ts | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 296411b76..d3c4a3919 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -82,6 +82,18 @@ export class Compiler { private readonly _artifactsDir: string; private readonly _solcVersionIfExists: string | undefined; private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; + private static async _doesFileExistAsync(filePath: string): Promise { + try { + await fsWrapper.accessAsync( + filePath, + // node says we need to use bitwise, but tslint says no: + fs.constants.F_OK | fs.constants.R_OK, // tslint:disable-line:no-bitwise + ); + } catch (err) { + return false; + } + return true; + } private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { @@ -91,9 +103,8 @@ export class Compiler { } const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); + if (await Compiler._doesFileExistAsync(compilerBinFilename)) { + solcjs = (await fsWrapper.readFileAsync(compilerBinFilename)).toString(); } else { logUtils.log(`Downloading ${fullSolcVersion}...`); const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; @@ -103,7 +114,10 @@ export class Compiler { throw new Error(`Failed to load ${fullSolcVersion}`); } solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); + await fsWrapper.writeFileAsync(compilerBinFilename, solcjs); + } + if (solcjs.length === 0) { + throw new Error('No compiler available'); } const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); return { solcInstance, fullSolcVersion }; diff --git a/packages/sol-compiler/src/utils/fs_wrapper.ts b/packages/sol-compiler/src/utils/fs_wrapper.ts index 6e3547a76..44c97bd1e 100644 --- a/packages/sol-compiler/src/utils/fs_wrapper.ts +++ b/packages/sol-compiler/src/utils/fs_wrapper.ts @@ -12,4 +12,5 @@ export const fsWrapper = { removeFileAsync: promisify(fs.unlink), statAsync: promisify(fs.stat), appendFileAsync: promisify(fs.appendFile), + accessAsync: promisify(fs.access), }; -- cgit v1.2.3 From 445177bf420049041ade4d7526a5f4a8194bd216 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 15:26:20 -0700 Subject: move doesFileExist to fsWrapper --- packages/sol-compiler/src/compiler.ts | 14 +------------- packages/sol-compiler/src/utils/fs_wrapper.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'packages/sol-compiler') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index d3c4a3919..2e7120361 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -82,18 +82,6 @@ export class Compiler { private readonly _artifactsDir: string; private readonly _solcVersionIfExists: string | undefined; private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; - private static async _doesFileExistAsync(filePath: string): Promise { - try { - await fsWrapper.accessAsync( - filePath, - // node says we need to use bitwise, but tslint says no: - fs.constants.F_OK | fs.constants.R_OK, // tslint:disable-line:no-bitwise - ); - } catch (err) { - return false; - } - return true; - } private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { @@ -103,7 +91,7 @@ export class Compiler { } const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; - if (await Compiler._doesFileExistAsync(compilerBinFilename)) { + if (await fsWrapper.doesFileExistAsync(compilerBinFilename)) { solcjs = (await fsWrapper.readFileAsync(compilerBinFilename)).toString(); } else { logUtils.log(`Downloading ${fullSolcVersion}...`); diff --git a/packages/sol-compiler/src/utils/fs_wrapper.ts b/packages/sol-compiler/src/utils/fs_wrapper.ts index 44c97bd1e..8d6800276 100644 --- a/packages/sol-compiler/src/utils/fs_wrapper.ts +++ b/packages/sol-compiler/src/utils/fs_wrapper.ts @@ -13,4 +13,16 @@ export const fsWrapper = { statAsync: promisify(fs.stat), appendFileAsync: promisify(fs.appendFile), accessAsync: promisify(fs.access), + doesFileExistAsync: async (filePath: string): Promise => { + try { + await fsWrapper.accessAsync( + filePath, + // node says we need to use bitwise, but tslint says no: + fs.constants.F_OK | fs.constants.R_OK, // tslint:disable-line:no-bitwise + ); + } catch (err) { + return false; + } + return true; + }, }; -- cgit v1.2.3