aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonid Logvinov <logvinov.leon@gmail.com>2018-07-12 17:53:21 +0800
committerGitHub <noreply@github.com>2018-07-12 17:53:21 +0800
commit34a903516439ec64073cfcb10cee87a9c4db902e (patch)
tree44f8a25ecfd3d860ffb9dc05f7494593744b1a0e
parentb82fdd59e70e92ef139f5eeed8ed383a89866c7d (diff)
parent4b60a3cbab3a97125499cb89d9c253deebfb7d2d (diff)
downloaddexon-sol-tools-34a903516439ec64073cfcb10cee87a9c4db902e.tar.gz
dexon-sol-tools-34a903516439ec64073cfcb10cee87a9c4db902e.tar.zst
dexon-sol-tools-34a903516439ec64073cfcb10cee87a9c4db902e.zip
Merge pull request #788 from feuGeneA/abi-gen-ignore-unchanged
Using timestamps, skip generation of already-up-to-date contract wrappers
-rw-r--r--.circleci/config.yml8
-rw-r--r--packages/abi-gen/CHANGELOG.json9
-rwxr-xr-xpackages/abi-gen/bin/abi-gen.js2
-rw-r--r--packages/abi-gen/coverage/.gitkeep0
-rw-r--r--packages/abi-gen/package.json15
-rw-r--r--packages/abi-gen/src/index.ts26
-rw-r--r--packages/abi-gen/src/utils.ts24
-rw-r--r--packages/abi-gen/test/utils_test.ts86
-rw-r--r--yarn.lock64
9 files changed, 202 insertions, 32 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 7027e3999..3393da379 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -65,6 +65,7 @@ jobs:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0xproject/0x.js
+ - run: yarn wsrun test:circleci @0xproject/abi-gen
- run: yarn wsrun test:circleci @0xproject/assert
- run: yarn wsrun test:circleci @0xproject/base-contract
- run: yarn wsrun test:circleci @0xproject/connect
@@ -84,6 +85,10 @@ jobs:
paths:
- ~/repo/packages/0x.js/coverage/lcov.info
- save_cache:
+ key: coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
+ paths:
+ - ~/repo/packages/abi-gen/coverage/lcov.info
+ - save_cache:
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/assert/coverage/lcov.info
@@ -162,6 +167,9 @@ jobs:
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
+ - coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
+ - restore_cache:
+ keys:
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
diff --git a/packages/abi-gen/CHANGELOG.json b/packages/abi-gen/CHANGELOG.json
index 38b72dbf3..ef8f5dd39 100644
--- a/packages/abi-gen/CHANGELOG.json
+++ b/packages/abi-gen/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "0.4.1",
+ "changes": [
+ {
+ "note": "skip generation of wrappers that are already up to date",
+ "pr": 788
+ }
+ ]
+ },
+ {
"version": "0.4.0",
"changes": [
{
diff --git a/packages/abi-gen/bin/abi-gen.js b/packages/abi-gen/bin/abi-gen.js
index c46eb9b66..8d6bdccf8 100755
--- a/packages/abi-gen/bin/abi-gen.js
+++ b/packages/abi-gen/bin/abi-gen.js
@@ -1,2 +1,2 @@
#!/usr/bin/env node
-require('../lib/index.js')
+require('../lib/src/index.js')
diff --git a/packages/abi-gen/coverage/.gitkeep b/packages/abi-gen/coverage/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/abi-gen/coverage/.gitkeep
diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json
index 7d7a20e68..4fb335545 100644
--- a/packages/abi-gen/package.json
+++ b/packages/abi-gen/package.json
@@ -12,6 +12,11 @@
"lint": "tslint --project .",
"clean": "shx rm -rf lib scripts",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
+ "test": "yarn run_mocha",
+ "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
+ "test:circleci": "yarn test:coverage",
+ "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
+ "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"bin": {
@@ -31,11 +36,13 @@
"@0xproject/utils": "^0.7.2",
"ethereum-types": "^0.0.2",
"chalk": "^2.3.0",
+ "ethereum-types": "^0.0.2",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
"lodash": "^4.17.4",
- "rimraf": "^2.6.2",
"mkdirp": "^0.5.1",
+ "sleep": "^5.1.1",
+ "tmp": "^0.0.33",
"to-snake-case": "^1.0.0",
"yargs": "^10.0.3"
},
@@ -43,13 +50,17 @@
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@types/glob": "5.0.35",
- "@types/rimraf": "^2.0.2",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
"@types/node": "^8.0.53",
+ "@types/sleep": "^0.0.7",
+ "@types/tmp": "^0.0.33",
"@types/yargs": "^10.0.0",
+ "chai": "^4.1.2",
"copyfiles": "^1.2.0",
+ "dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
+ "mocha": "^5.2.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",
diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts
index 47f2c404b..753bb2cce 100644
--- a/packages/abi-gen/src/index.ts
+++ b/packages/abi-gen/src/index.ts
@@ -3,16 +3,12 @@
import { abiUtils, logUtils } from '@0xproject/utils';
import chalk from 'chalk';
import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from 'ethereum-types';
-import * as fs from 'fs';
import { sync as globSync } from 'glob';
import * as Handlebars from 'handlebars';
import * as _ from 'lodash';
import * as mkdirp from 'mkdirp';
-import * as rimraf from 'rimraf';
import * as yargs from 'yargs';
-import toSnakeCase = require('to-snake-case');
-
import { ContextData, ContractsBackend, ParamKind } from './types';
import { utils } from './utils';
@@ -71,16 +67,6 @@ function registerPartials(partialsGlob: string): void {
}
}
-function writeOutputFile(name: string, renderedTsCode: string): void {
- let fileName = toSnakeCase(name);
- // HACK: Snake case doesn't make a lot of sense for abbreviated names but we can't reliably detect abbreviations
- // so we special-case the abbreviations we use.
- fileName = fileName.replace('z_r_x', 'zrx').replace('e_r_c', 'erc');
- const filePath = `${args.output}/${fileName}.ts`;
- fs.writeFileSync(filePath, renderedTsCode);
- logUtils.log(`Created: ${chalk.bold(filePath)}`);
-}
-
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
if (args.partials) {
@@ -97,7 +83,6 @@ if (_.isEmpty(abiFileNames)) {
process.exit(1);
} else {
logUtils.log(`Found ${chalk.green(`${abiFileNames.length}`)} ${chalk.bold('ABI')} files`);
- rimraf.sync(args.output);
mkdirp.sync(args.output);
}
for (const abiFileName of abiFileNames) {
@@ -120,6 +105,14 @@ for (const abiFileName of abiFileNames) {
process.exit(1);
}
+ const outFileName = utils.makeOutputFileName(namedContent.name);
+ const outFilePath = `${args.output}/${outFileName}.ts`;
+
+ if (utils.isOutputFileUpToDate(abiFileName, outFilePath)) {
+ logUtils.log(`Aready up to date: ${chalk.bold(outFilePath)}`);
+ continue;
+ }
+
let ctor = ABI.find((abi: AbiDefinition) => abi.type === ABI_TYPE_CONSTRUCTOR) as ConstructorAbi;
if (_.isUndefined(ctor)) {
ctor = utils.getEmptyConstructor(); // The constructor exists, but it's implicit in JSON's ABI definition
@@ -154,5 +147,6 @@ for (const abiFileName of abiFileNames) {
events: eventAbis,
};
const renderedTsCode = template(contextData);
- writeOutputFile(namedContent.name, renderedTsCode);
+ utils.writeOutputFile(outFilePath, renderedTsCode);
+ logUtils.log(`Created: ${chalk.bold(outFilePath)}`);
}
diff --git a/packages/abi-gen/src/utils.ts b/packages/abi-gen/src/utils.ts
index 66390174c..56b996ce3 100644
--- a/packages/abi-gen/src/utils.ts
+++ b/packages/abi-gen/src/utils.ts
@@ -2,6 +2,7 @@ import { AbiType, ConstructorAbi, DataItem } from 'ethereum-types';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as path from 'path';
+import toSnakeCase = require('to-snake-case');
import { ContractsBackend, ParamKind } from './types';
@@ -92,4 +93,27 @@ export const utils = {
inputs: [],
};
},
+ makeOutputFileName(name: string): string {
+ let fileName = toSnakeCase(name);
+ // HACK: Snake case doesn't make a lot of sense for abbreviated names but we can't reliably detect abbreviations
+ // so we special-case the abbreviations we use.
+ fileName = fileName.replace('z_r_x', 'zrx').replace('e_r_c', 'erc');
+ return fileName;
+ },
+ writeOutputFile(filePath: string, renderedTsCode: string): void {
+ fs.writeFileSync(filePath, renderedTsCode);
+ },
+ isOutputFileUpToDate(abiFile: string, outputFile: string): boolean {
+ const abiFileModTimeMs = fs.statSync(abiFile).mtimeMs;
+ try {
+ const outFileModTimeMs = fs.statSync(outputFile).mtimeMs;
+ return outFileModTimeMs > abiFileModTimeMs;
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ return false;
+ } else {
+ throw err;
+ }
+ }
+ },
};
diff --git a/packages/abi-gen/test/utils_test.ts b/packages/abi-gen/test/utils_test.ts
new file mode 100644
index 000000000..c6147df38
--- /dev/null
+++ b/packages/abi-gen/test/utils_test.ts
@@ -0,0 +1,86 @@
+import * as chai from 'chai';
+import * as dirtyChai from 'dirty-chai';
+import * as fs from 'fs';
+import 'mocha';
+import * as sleep from 'sleep';
+import * as tmp from 'tmp';
+
+import { utils } from '../src/utils';
+
+tmp.setGracefulCleanup(); // remove tmp files even if there are failures
+
+chai.use(dirtyChai);
+
+const expect = chai.expect;
+
+const SLEEP_MS = 10; // time to wait before re-timestamping a file
+
+describe('makeOutputFileName()', () => {
+ it('should handle Metacoin usage', () => {
+ expect(utils.makeOutputFileName('Metacoin')).to.equal('metacoin');
+ });
+ it('should handle special zrx_token case', () => {
+ expect(utils.makeOutputFileName('ZRXToken')).to.equal('zrx_token');
+ });
+ it('should handle special erc_token case', () => {
+ expect(utils.makeOutputFileName('ERC20Token')).to.equal('erc20_token');
+ });
+});
+
+describe('writeOutputFile()', () => {
+ let tempFilePath: string;
+ before(() => {
+ tempFilePath = tmp.fileSync(
+ { discardDescriptor: true }, // close file (so we can update it)
+ ).name;
+ });
+ it('should write content to output file', () => {
+ const content = 'hello world';
+
+ utils.writeOutputFile(tempFilePath, content);
+
+ expect(fs.readFileSync(tempFilePath).toString()).to.equal(content);
+ });
+});
+
+describe('isOutputFileUpToDate()', () => {
+ it('should throw ENOENT when there is no abi file', () => {
+ expect(utils.isOutputFileUpToDate.bind('nonexistant1', 'nonexistant2')).to.throw('ENOENT');
+ });
+
+ describe('when the abi input file exists', () => {
+ let abiFile: string;
+ before(() => {
+ abiFile = tmp.fileSync(
+ { discardDescriptor: true }, // close file (set timestamp)
+ ).name;
+ });
+
+ describe('without an existing output file', () => {
+ it('should return false', () => {
+ expect(utils.isOutputFileUpToDate(abiFile, 'nonexistant_file')).to.be.false();
+ });
+ });
+
+ describe('with an existing output file', () => {
+ let outputFile: string;
+ before(() => {
+ sleep.msleep(SLEEP_MS); // to ensure different timestamp
+ outputFile = tmp.fileSync(
+ { discardDescriptor: true }, // close file (set timestamp)
+ ).name;
+ });
+
+ it('should return true when output file and is newer than abi file', async () => {
+ expect(utils.isOutputFileUpToDate(abiFile, outputFile)).to.be.true();
+ });
+
+ it('should return false when output file exists but is older than abi file', () => {
+ sleep.msleep(SLEEP_MS); // to ensure different timestamp
+ fs.closeSync(fs.openSync(abiFile, 'w')); // touch abi file
+
+ expect(utils.isOutputFileUpToDate(abiFile, outputFile)).to.be.false();
+ });
+ });
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index a7c8a627b..a8a897511 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -534,10 +534,18 @@
version "2.3.7"
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.7.tgz#e92c2fed3297eae078d78d1da032b26788b4af86"
+"@types/sleep@^0.0.7":
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/@types/sleep/-/sleep-0.0.7.tgz#0572b5d06978b4305671c614b0f68b4640ce7d43"
+
"@types/solidity-parser-antlr@^0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@types/solidity-parser-antlr/-/solidity-parser-antlr-0.2.1.tgz#29ff386773a72a06c8a9c40c666d2a1cea53c2ed"
+"@types/tmp@^0.0.33":
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
+
"@types/uuid@^3.4.2":
version "3.4.3"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.3.tgz#121ace265f5569ce40f4f6d0ff78a338c732a754"
@@ -2025,6 +2033,10 @@ browser-stdout@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
+browser-stdout@1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
+
browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6:
version "1.2.0"
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
@@ -2731,7 +2743,7 @@ commander@2.13.0, commander@~2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
-commander@^2.12.1, commander@^2.8.1, commander@^2.9.0:
+commander@2.15.1, commander@^2.12.1, commander@^2.8.1, commander@^2.9.0:
version "2.15.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
@@ -3692,7 +3704,7 @@ diff@3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
-diff@^3.1.0, diff@^3.2.0, diff@^3.3.1, diff@^3.5.0:
+diff@3.5.0, diff@^3.1.0, diff@^3.2.0, diff@^3.3.1, diff@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
@@ -4469,9 +4481,9 @@ ethereumjs-wallet@~0.6.0:
utf8 "^2.1.1"
uuid "^2.0.1"
-ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22:
- version "3.0.18"
- resolved "https://codeload.github.com/0xproject/ethers.js/tar.gz/b91342bd200d142af0165d6befddf783c8ae8447"
+ethers@3.0.22:
+ version "3.0.22"
+ resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.22.tgz#7fab1ea16521705837aa43c15831877b2716b436"
dependencies:
aes-js "3.0.0"
bn.js "^4.4.0"
@@ -5630,6 +5642,10 @@ growl@1.10.3:
version "1.10.3"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f"
+growl@1.10.5:
+ version "1.10.5"
+ resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
+
gud@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0"
@@ -7948,7 +7964,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
-"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
@@ -8039,6 +8055,22 @@ mocha@^4.0.1:
mkdirp "0.5.1"
supports-color "4.4.0"
+mocha@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
+ dependencies:
+ browser-stdout "1.3.1"
+ commander "2.15.1"
+ debug "3.1.0"
+ diff "3.5.0"
+ escape-string-regexp "1.0.5"
+ glob "7.1.2"
+ growl "1.10.5"
+ he "1.1.1"
+ minimatch "3.0.4"
+ mkdirp "0.5.1"
+ supports-color "5.4.0"
+
mock-fs@^4.1.0:
version "4.4.2"
resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.4.2.tgz#09dec5313f97095a450be6aa2ad8ab6738d63d6b"
@@ -8120,7 +8152,7 @@ mz@^2.6.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
-nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.3, nan@^2.6.2:
+nan@>=2.5.1, nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.3, nan@^2.6.2:
version "2.10.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
@@ -10998,6 +11030,12 @@ slash@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+sleep@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/sleep/-/sleep-5.1.1.tgz#878fa1d44d08eeb0f26fb2018ef8629eb1a3ab94"
+ dependencies:
+ nan ">=2.5.1"
+
slice-ansi@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
@@ -11613,6 +11651,12 @@ supports-color@4.4.0:
dependencies:
has-flag "^2.0.0"
+supports-color@5.4.0, supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0:
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
+ dependencies:
+ has-flag "^3.0.0"
+
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -11629,12 +11673,6 @@ supports-color@^4.2.1:
dependencies:
has-flag "^2.0.0"
-supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0:
- version "5.4.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
- dependencies:
- has-flag "^3.0.0"
-
svgo@^0.7.0:
version "0.7.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"