Skip to content

Commit 849e34a

Browse files
authored
Merge pull request #369 from embark-framework/features/mapping-urls
Add new mappings for Solidity (HTTP and Github)
2 parents 0948b04 + a435bcc commit 849e34a

File tree

15 files changed

+670
-396
lines changed

15 files changed

+670
-396
lines changed

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
},
77
"extends": "eslint:recommended",
88
"parserOptions": {
9-
"sourceType": "module"
9+
"sourceType": "module",
10+
"ecmaVersion": 2017
1011
},
1112
"rules": {
1213
"accessor-pairs": "error",

lib/core/config.js

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
var fs = require('./fs.js');
2-
var File = require('./file.js');
3-
var Plugins = require('./plugins.js');
4-
var utils = require('../utils/utils.js');
5-
var path = require('path');
1+
const fs = require('./fs.js');
2+
const File = require('./file.js');
3+
const Plugins = require('./plugins.js');
4+
const utils = require('../utils/utils.js');
5+
const path = require('path');
6+
7+
const httpContractDir = '.embark/contracts/';
68

79
var Config = function(options) {
810
this.env = options.env;
@@ -142,17 +144,58 @@ Config.prototype.loadContractsConfigFile = function() {
142144
this.contractsConfig = this._mergeConfig(configFilePath, configObject, this.env);
143145
};
144146

147+
Config.prototype.getExternalContractUrl = function (contract) {
148+
let url;
149+
const RAW_URL = 'https://raw.githubusercontent.com/';
150+
const MALFORMED_ERROR = 'Malformed Github URL for ';
151+
if (contract.file.startsWith('https://github')) {
152+
const match = contract.file.match(/https:\/\/github\.[a-z]+\/(.*)/);
153+
if (!match) {
154+
this.logger.error(MALFORMED_ERROR + contract.file);
155+
return '';
156+
}
157+
url = `${RAW_URL}${match[1].replace('blob/', '')}`;
158+
} else if (contract.file.startsWith('git')) {
159+
// Match values
160+
// [0] entire input
161+
// [1] git://
162+
// [2] user
163+
// [3] repository
164+
// [4] path
165+
// [5] branch
166+
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_\-.]*)?/
168+
);
169+
if (!match) {
170+
this.logger.error(MALFORMED_ERROR + contract.file);
171+
return '';
172+
}
173+
let branch = match[5];
174+
if (!branch) {
175+
branch = 'master';
176+
}
177+
url = `${RAW_URL}${match[2]}/${match[3]}/${branch}/${match[4]}`;
178+
} else {
179+
url = contract.file;
180+
}
181+
return url;
182+
};
183+
145184
Config.prototype.loadExternalContractsFiles = function() {
146185
let contracts = this.contractsConfig.contracts;
147186
for (let contractName in contracts) {
148187
let contract = contracts[contractName];
149188
if (!contract.file) {
150189
continue;
151190
}
152-
if (fs.existsSync(contract.file)) {
153-
this.contractsFiles.push(new File({filename: contract.file, type: "dapp_file", basedir: '', path: contract.file}));
191+
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}));
195+
} else if (fs.existsSync(contract.file)) {
196+
this.contractsFiles.push(new File({filename: contract.file, type: File.types.dapp_file, basedir: '', path: contract.file}));
154197
} else if (fs.existsSync(path.join('./node_modules/', contract.file))) {
155-
this.contractsFiles.push(new File({filename: path.join('./node_modules/', contract.file), type: "dapp_file", basedir: '', path: path.join('./node_modules/', contract.file)}));
198+
this.contractsFiles.push(new File({filename: path.join('./node_modules/', contract.file), type: File.types.dapp_file, basedir: '', path: path.join('./node_modules/', contract.file)}));
156199
} else {
157200
this.logger.error("contract file not found: " + contract.file);
158201
}
@@ -216,6 +259,7 @@ Config.prototype.loadEmbarkConfigFile = function() {
216259
}).map((dir) => {
217260
return dir.split("*.")[0];
218261
});
262+
this.contractDirectories.push(httpContractDir);
219263

220264
this.buildDir = this.embarkConfig.buildDir;
221265
this.configDir = this.embarkConfig.config;
@@ -258,7 +302,7 @@ Config.prototype.loadFiles = function(files) {
258302
return (file[0] === '$' || file.indexOf('.') >= 0);
259303
}).filter(function(file) {
260304
let basedir = findMatchingExpression(file, files);
261-
readFiles.push(new File({filename: file, type: "dapp_file", basedir: basedir, path: file}));
305+
readFiles.push(new File({filename: file, type: File.types.dapp_file, basedir: basedir, path: file}));
262306
});
263307

264308
var filesFromPlugins = [];
@@ -291,7 +335,7 @@ Config.prototype.loadPluginContractFiles = function() {
291335
contractsPlugins.forEach(function(plugin) {
292336
plugin.contractsFiles.forEach(function(file) {
293337
var filename = file.replace('./','');
294-
self.contractsFiles.push(new File({filename: filename, type: 'custom', resolver: function(callback) {
338+
self.contractsFiles.push(new File({filename: filename, type: File.types.custom, resolver: function(callback) {
295339
callback(plugin.loadPluginFile(file));
296340
}}));
297341
});

lib/core/file.js

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,77 @@
1-
let fs = require('./fs.js');
1+
const async = require('async');
2+
const fs = require('./fs.js');
3+
const path = require('path');
4+
const request = require('request');
25

36
class File {
47

5-
constructor(options) {
8+
constructor (options) {
69
this.filename = options.filename;
710
this.type = options.type;
811
this.path = options.path;
912
this.basedir = options.basedir;
1013
this.resolver = options.resolver;
1114
}
1215

13-
content(callback) {
14-
if (this.type === 'embark_internal') {
16+
downloadFile (callback) {
17+
const self = this;
18+
async.waterfall([
19+
function makeTheDir(next) {
20+
fs.mkdirp(path.dirname(self.filename), (err) => {
21+
if (err) {
22+
return next(err);
23+
}
24+
next();
25+
});
26+
},
27+
function downloadTheFile(next) {
28+
request(self.path)
29+
.on('response', function (response) {
30+
if (response.statusCode !== 200) {
31+
next('Getting file returned code ' + response.statusCode);
32+
}
33+
})
34+
.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+
});
41+
},
42+
function readFile(next) {
43+
fs.readFile(self.path, next);
44+
}
45+
], (err, content) => {
46+
if (err) {
47+
console.error('Error while downloading the file', err);
48+
return callback('');
49+
}
50+
callback(content.toString());
51+
});
52+
}
53+
54+
content (callback) {
55+
if (this.type === File.types.embark_internal) {
1556
return callback(fs.readFileSync(fs.embarkPath(this.path)).toString());
16-
} else if (this.type === 'dapp_file') {
57+
} else if (this.type === File.types.dapp_file) {
1758
return callback(fs.readFileSync(this.path).toString());
18-
} else if (this.type === 'custom') {
59+
} else if (this.type === File.types.custom) {
1960
return this.resolver(callback);
61+
} else if (this.type === File.types.http) {
62+
this.downloadFile(callback);
2063
} else {
2164
throw new Error("unknown file: " + this.filename);
2265
}
2366
}
2467

2568
}
2669

70+
File.types = {
71+
embark_internal: 'embark_internal',
72+
dapp_file: 'dapp_file',
73+
custom: 'custom',
74+
http: 'http'
75+
};
76+
2777
module.exports = File;

lib/core/fs.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ function mkdirpSync() {
77
return fs.mkdirpSync.apply(fs.mkdirpSync, arguments);
88
}
99

10+
function mkdirp() {
11+
return fs.mkdirp.apply(fs.mkdirp, arguments);
12+
}
13+
1014
function copySync() {
1115
return fs.copySync.apply(fs.copySync, arguments);
1216
}
@@ -19,6 +23,10 @@ function writeFileSync() {
1923
return fs.writeFileSync.apply(fs.writeFileSync, arguments);
2024
}
2125

26+
function readFile() {
27+
return fs.readFile.apply(fs.readFile, arguments);
28+
}
29+
2230
function readFileSync() {
2331
return fs.readFileSync.apply(fs.readFileSync, arguments);
2432
}
@@ -54,9 +62,15 @@ function dappPath() {
5462
return utils.joinPath(utils.pwd(), ...arguments);
5563
}
5664

65+
function createWriteStream() {
66+
return fs.createWriteStream.apply(fs.createWriteStream, arguments);
67+
}
68+
5769
module.exports = {
5870
mkdirpSync: mkdirpSync,
71+
mkdirp,
5972
copySync: copySync,
73+
readFile,
6074
readFileSync: readFileSync,
6175
appendFileSync: appendFileSync,
6276
writeFileSync: writeFileSync,
@@ -65,5 +79,6 @@ module.exports = {
6579
existsSync: existsSync,
6680
removeSync: removeSync,
6781
embarkPath: embarkPath,
68-
dappPath: dappPath
82+
dappPath: dappPath,
83+
createWriteStream
6984
};

lib/modules/solidity/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ class Solidity {
2727
}
2828

2929
file.content(function(fileContent) {
30+
if (!fileContent) {
31+
self.logger.error('Error while loading the content of ' + filename);
32+
return fileCb();
33+
}
3034
input[filename] = {content: fileContent.replace(/\r\n/g, '\n')};
3135
fileCb();
3236
});

lib/tests/run_tests.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
var utils = require('../utils/utils.js');
1+
const utils = require('../utils/utils.js');
22

33
module.exports = {
44
run: function(filepath) {
5-
var Mocha = require('mocha'),
6-
fs = require('fs'),
5+
const Mocha = require('mocha'),
6+
fs = require('fs-extra'),
77
path = require('path');
88

9-
var mocha = new Mocha();
9+
const mocha = new Mocha();
1010

1111
if (filepath) {
1212
if (filepath.substr(-1) === '/') {
@@ -60,11 +60,14 @@ module.exports = {
6060
};
6161

6262
// Run the tests.
63-
let runner = mocha.run(function(failures){
64-
process.on('exit', function () {
65-
process.exit(failures); // exit with non-zero status if there were failures
63+
let runner = mocha.run(function(failures) {
64+
// Clean contracts folder for next test run
65+
fs.remove('.embark/contracts', (_err) => {
66+
process.on('exit', function () {
67+
process.exit(failures); // exit with non-zero status if there were failures
68+
});
69+
process.exit();
6670
});
67-
process.exit();
6871
});
6972

7073
runner.on('suite', function() {

0 commit comments

Comments
 (0)