Skip to content

Commit 9a79df6

Browse files
authored
Merge pull request #371 from embark-framework/features/download-imports-too
Download Imports for downloaded contracts
2 parents e1a9023 + df5b647 commit 9a79df6

File tree

11 files changed

+273
-87
lines changed

11 files changed

+273
-87
lines changed

lib/constants.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"httpContractsDirectory": ".embark/contracts/"
3+
}

lib/core/config.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ const File = require('./file.js');
33
const Plugins = require('./plugins.js');
44
const utils = require('../utils/utils.js');
55
const path = require('path');
6-
7-
const httpContractDir = '.embark/contracts/';
6+
const constants = require('../constants');
87

98
var Config = function(options) {
109
this.env = options.env;
@@ -152,7 +151,7 @@ Config.prototype.getExternalContractUrl = function (contract) {
152151
const match = contract.file.match(/https:\/\/github\.[a-z]+\/(.*)/);
153152
if (!match) {
154153
this.logger.error(MALFORMED_ERROR + contract.file);
155-
return '';
154+
return null;
156155
}
157156
url = `${RAW_URL}${match[1].replace('blob/', '')}`;
158157
} else if (contract.file.startsWith('git')) {
@@ -164,11 +163,11 @@ Config.prototype.getExternalContractUrl = function (contract) {
164163
// [4] path
165164
// [5] branch
166165
const match = contract.file.match(
167-
/(git:\/\/)?github\.[a-z]+\/([a-zA-Z0-9_\-.]+)\/([a-zA-Z0-9_\-7]+)\/([a-zA-Z0-9_\-\/.]+)#?([a-zA-Z0-1_\-.]*)?/
166+
/(git:\/\/)?github\.[a-z]+\/([a-zA-Z0-9_\-.]+)\/([a-zA-Z0-9_\-]+)\/([a-zA-Z0-9_\-\/.]+)#?([a-zA-Z0-1_\-.]*)?/
168167
);
169168
if (!match) {
170169
this.logger.error(MALFORMED_ERROR + contract.file);
171-
return '';
170+
return null;
172171
}
173172
let branch = match[5];
174173
if (!branch) {
@@ -178,7 +177,13 @@ Config.prototype.getExternalContractUrl = function (contract) {
178177
} else {
179178
url = contract.file;
180179
}
181-
return url;
180+
const match = url.match(
181+
/\.[a-z]+\/([a-zA-Z0-9_\-\/.]+)/
182+
);
183+
return {
184+
url,
185+
filePath: match[1]
186+
};
182187
};
183188

184189
Config.prototype.loadExternalContractsFiles = function() {
@@ -189,9 +194,12 @@ Config.prototype.loadExternalContractsFiles = function() {
189194
continue;
190195
}
191196
if (contract.file.startsWith('http') || contract.file.startsWith('git')) {
192-
const url = this.getExternalContractUrl(contract);
193-
const localFile = httpContractDir + path.basename(url);
194-
this.contractsFiles.push(new File({filename: localFile, type: File.types.http, basedir: '', path: url}));
197+
const fileObj = this.getExternalContractUrl(contract);
198+
if (!fileObj) {
199+
return this.logger.error("HTTP contract file not found: " + contract.file);
200+
}
201+
const localFile = constants.httpContractsDirectory + fileObj.filePath;
202+
this.contractsFiles.push(new File({filename: localFile, type: File.types.http, basedir: '', path: fileObj.url}));
195203
} else if (fs.existsSync(contract.file)) {
196204
this.contractsFiles.push(new File({filename: contract.file, type: File.types.dapp_file, basedir: '', path: contract.file}));
197205
} else if (fs.existsSync(path.join('./node_modules/', contract.file))) {
@@ -259,7 +267,7 @@ Config.prototype.loadEmbarkConfigFile = function() {
259267
}).map((dir) => {
260268
return dir.split("*.")[0];
261269
});
262-
this.contractDirectories.push(httpContractDir);
270+
this.contractDirectories.push(constants.httpContractsDirectory);
263271

264272
this.buildDir = this.embarkConfig.buildDir;
265273
this.configDir = this.embarkConfig.config;

lib/core/file.js

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,59 @@ class File {
1313
this.resolver = options.resolver;
1414
}
1515

16-
downloadFile (callback) {
16+
parseFileForImport(content, callback) {
17+
const self = this;
18+
if (self.filename.indexOf('.sol') < 0) {
19+
// Only supported in Solidity
20+
return callback();
21+
}
22+
const regex = /import "([a-zA-Z0-9_\-.\\\/]+)";/g;
23+
let matches;
24+
const filesToDownload = [];
25+
const pathWithoutFile = path.dirname(self.path);
26+
while ((matches = regex.exec(content))) {
27+
filesToDownload.push({
28+
fileRelativePath: path.join(path.dirname(self.filename), matches[1]),
29+
url: `${pathWithoutFile}/${matches[1]}`
30+
});
31+
}
32+
33+
async.each(filesToDownload, ((fileObj, eachCb) => {
34+
self.downloadFile(fileObj.fileRelativePath, fileObj.url, (_content) => {
35+
eachCb();
36+
});
37+
}), callback);
38+
}
39+
40+
downloadFile (filename, url, callback) {
1741
const self = this;
1842
async.waterfall([
1943
function makeTheDir(next) {
20-
fs.mkdirp(path.dirname(self.filename), (err) => {
44+
fs.mkdirp(path.dirname(filename), (err) => {
2145
if (err) {
2246
return next(err);
2347
}
2448
next();
2549
});
2650
},
2751
function downloadTheFile(next) {
28-
request(self.path)
52+
request(url)
2953
.on('response', function (response) {
3054
if (response.statusCode !== 200) {
3155
next('Getting file returned code ' + response.statusCode);
3256
}
3357
})
3458
.on('error', next)
35-
.pipe(fs.createWriteStream(self.filename))
36-
.on('finish', () => {
37-
self.path = self.filename;
38-
self.type = File.types.dapp_file;
39-
next();
40-
});
59+
.pipe(fs.createWriteStream(filename))
60+
.on('finish', next);
4161
},
4262
function readFile(next) {
43-
fs.readFile(self.path, next);
63+
fs.readFile(filename, next);
64+
},
65+
function parseForImports(content, next) {
66+
self.parseFileForImport(content, (err) => {
67+
next(err, content);
68+
});
4469
}
4570
], (err, content) => {
4671
if (err) {
@@ -59,7 +84,14 @@ class File {
5984
} else if (this.type === File.types.custom) {
6085
return this.resolver(callback);
6186
} else if (this.type === File.types.http) {
62-
this.downloadFile(callback);
87+
this.downloadFile(this.filename, this.path, (content) => {
88+
if (!content) {
89+
return callback(content);
90+
}
91+
this.path = this.filename;
92+
this.type = File.types.dapp_file;
93+
callback(content);
94+
});
6395
} else {
6496
throw new Error("unknown file: " + this.filename);
6597
}

lib/modules/solidity/solcP.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
let solc;
22

3-
let fs = require('fs-extra');
4-
let path = require('path');
3+
const fs = require('fs-extra');
4+
const path = require('path');
5+
const constants = require('../../constants');
56

67
function findImports(filename) {
78
if (fs.existsSync(filename)) {
@@ -10,6 +11,9 @@ function findImports(filename) {
1011
if (fs.existsSync(path.join('./node_modules/', filename))) {
1112
return {contents: fs.readFileSync(path.join('./node_modules/', filename)).toString()};
1213
}
14+
if (fs.existsSync(path.join(constants.httpContractsDirectory, filename))) {
15+
return {contents: fs.readFileSync(path.join('./.embark/contracts', filename)).toString()};
16+
}
1317
return {error: 'File not found'};
1418
}
1519

package-lock.json

Lines changed: 92 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,6 @@
8888
"matchdep": "^1.0.1",
8989
"mocha": "^3.2.0",
9090
"mocha-sinon": "^1.1.4",
91-
"sinon": "^1.15.4"
91+
"sinon": "^4.5.0"
9292
}
9393
}

0 commit comments

Comments
 (0)