From ee81b7e2099c6a78cb36144185c1b587b140a29d Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 6 Jul 2018 11:38:09 +0300 Subject: [PATCH 1/6] add support to download a template --- lib/cmd.js | 5 +-- lib/cmds/template_generator.js | 51 ++++++++++++++++++++++++++++ lib/core/fs.js | 8 ++++- lib/index.js | 6 +++- lib/utils/utils.js | 16 +++++++++ package.json | 1 + test/template.js | 61 ++++++++++++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 test/template.js diff --git a/lib/cmd.js b/lib/cmd.js index 2f09eb5dd..6267f373c 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -45,6 +45,7 @@ class Cmd { .description(__('New Application')) .option('--simple', __('create a barebones project meant only for contract development')) .option('--locale [locale]', __('language to use (default: en)')) + .option('--template [url]', __('download template')) .action(function (name, options) { i18n.setOrDetectLocale(options.locale); if (name === undefined) { @@ -63,7 +64,7 @@ class Cmd { if (options.simple) { embark.generateTemplate('simple', './', inputvalue); } else { - embark.generateTemplate('boilerplate', './', inputvalue); + embark.generateTemplate('boilerplate', './', inputvalue, options.template); } } }); @@ -71,7 +72,7 @@ class Cmd { if (options.simple) { embark.generateTemplate('simple', './', name); } else { - embark.generateTemplate('boilerplate', './', name); + embark.generateTemplate('boilerplate', './', name, options.template); } } }); diff --git a/lib/cmds/template_generator.js b/lib/cmds/template_generator.js index 8597fcc02..4fc779710 100644 --- a/lib/cmds/template_generator.js +++ b/lib/cmds/template_generator.js @@ -6,6 +6,26 @@ class TemplateGenerator { this.templateName = templateName; } + downloadAndGenerate(uri, destinationFolder, name) { + let {url, filePath} = this.getExternalProject(uri); + let tmpFilePath = fs.tmpDir(filePath); + + fs.mkdirpSync(utils.dirname(tmpFilePath)); + utils.downloadFile(url, tmpFilePath, () => { + let fspath = utils.joinPath(destinationFolder, name); + const decompress = require('decompress'); + + decompress(tmpFilePath, fspath, { + map: file => { + let fixed_path = file.path.split('/'); + fixed_path.shift(); // remove first directory + file.path = utils.joinPath(...fixed_path); + return file; + } + }); + }); + } + generate(destinationFolder, name) { let templatePath = fs.embarkPath(utils.joinPath('templates', this.templateName)); console.log(__('Initializing Embark Template....').green); @@ -31,6 +51,37 @@ class TemplateGenerator { console.log(__('For more info go to http://embark.status.im').green); } } + + getExternalProject(uri) { + const constants = require('../constants'); + const RAW_URL = 'https://github.com/'; + + let match = uri.match( + /\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/ + ); + + let url, folder; + + if (uri.startsWith('http')) { + url = uri + "/archive/master.zip" + folder = match[1] + } else if (uri.startsWith('github')) { + url = "https://" + uri + "/archive/master.zip" + folder = match[1] + } else if (uri.split('/').length === 2) { + url = "https://github.com/" + uri + "/archive/master.zip" + folder = uri + } else if (uri.indexOf('/') === -1) { + url = "https://github.com/embark-framework/embark-" + uri + "-template/archive/master.zip" + folder = "embark-framework/embark-" + uri + "-template" + } + + return { + url, + filePath: utils.joinPath(".embark/templates/", folder, "archive.zip") + }; + } + } module.exports = TemplateGenerator; diff --git a/lib/core/fs.js b/lib/core/fs.js index 6dbc12285..4e2e21792 100644 --- a/lib/core/fs.js +++ b/lib/core/fs.js @@ -86,6 +86,11 @@ function createWriteStream() { return fs.createWriteStream.apply(fs.createWriteStream, arguments); } +function tmpDir() { + let os = require('os'); + return utils.joinPath(os.tmpdir(), ...arguments); +} + module.exports = { mkdirpSync, mkdirp, @@ -105,5 +110,6 @@ module.exports = { removeSync, embarkPath, dappPath, - createWriteStream + createWriteStream, + tmpDir }; diff --git a/lib/index.js b/lib/index.js index f2dd51002..032287e13 100644 --- a/lib/index.js +++ b/lib/index.js @@ -53,10 +53,14 @@ class Embark { simulator.run(options); } - generateTemplate(templateName, destinationFolder, name) { + generateTemplate(templateName, destinationFolder, name, url) { this.context = [constants.contexts.templateGeneration]; let TemplateGenerator = require('./cmds/template_generator.js'); let templateGenerator = new TemplateGenerator(templateName); + + if (url) { + return templateGenerator.downloadAndGenerate(url, destinationFolder, name); + } templateGenerator.generate(destinationFolder, name); } diff --git a/lib/utils/utils.js b/lib/utils/utils.js index 172423d3f..b3a2fb38a 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -6,6 +6,11 @@ function joinPath() { return path.join.apply(path.join, arguments); } +function dirname() { + const path = require('path'); + return path.dirname.apply(path.dirname, arguments); +} + function filesMatchingPattern(files) { const globule = require('globule'); return globule.find(files, {nonull: true}); @@ -168,6 +173,15 @@ function extractTar(filename, packageDirectory, cb) { ); } +function extractZip(filename, packageDirectory, cb) { + const decompress = require('decompress'); + + decompress(filename, packageDirectory).then(files => { + console.log('done!'); + cb(); + }); +} + function proposeAlternative(word, _dictionary, _exceptions) { const propose = require('propose'); let exceptions = _exceptions || []; @@ -299,6 +313,7 @@ function buildUrlFromConfig (configObj){ module.exports = { joinPath: joinPath, + dirname: dirname, filesMatchingPattern: filesMatchingPattern, fileMatchesPattern: fileMatchesPattern, recursiveMerge: recursiveMerge, @@ -316,6 +331,7 @@ module.exports = { exit: exit, downloadFile: downloadFile, extractTar: extractTar, + extractZip: extractZip, proposeAlternative: proposeAlternative, pwd: pwd, getExternalContractUrl, diff --git a/package.json b/package.json index ed38bbe2c..2534ce7e3 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "colors": "^1.1.2", "commander": "^2.15.1", "css-loader": "^0.28.11", + "decompress": "^4.2.0", "deep-equal": "^1.0.1", "ejs": "^2.5.8", "embark-web3-provider-engine": "14.0.7", diff --git a/test/template.js b/test/template.js new file mode 100644 index 000000000..b539e7c9c --- /dev/null +++ b/test/template.js @@ -0,0 +1,61 @@ +/*globals describe, it*/ +const assert = require('assert'); +const TemplateGenerator = require('../lib/cmds/template_generator'); + +describe('TemplateGenerator', function () { + describe('getExternalProject', function () { + let templateGenerator; + + before(() => { + templateGenerator = new TemplateGenerator(); + }); + + describe('with github link', function () { + + it('return correct zip filename for https link', function (done) { + let result = templateGenerator.getExternalProject("https://github.com/embark-framework/embark"); + assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); + done(); + }); + + it('return correct zip filename for http link', function (done) { + let result = templateGenerator.getExternalProject("http://github.com/embark-framework/embark"); + assert.deepEqual(result.url, "http://github.com/embark-framework/embark/archive/master.zip"); + assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); + done(); + }); + + it('return correct zip filename without protocol specified ', function (done) { + let result = templateGenerator.getExternalProject("github.com/embark-framework/embark"); + assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); + done(); + }); + + it('return correct zip filename without protocol specified ', function (done) { + let result = templateGenerator.getExternalProject("github.com/embark-framework/embark"); + assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); + done(); + }); + + it('return correct zip filename with just username/repo specified', function (done) { + let result = templateGenerator.getExternalProject("embark-framework/embark"); + assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); + done(); + }); + + it('return correct zip filename with just embark template specified', function (done) { + let result = templateGenerator.getExternalProject("react"); + assert.deepEqual(result.url, "https://github.com/embark-framework/embark-react-template/archive/master.zip"); + assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark-react-template/archive.zip"); + done(); + }); + + }); + + }); +}); + From 215799f2bd1fbbc8fbd6bf685ae80f7bcc8638a6 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 6 Jul 2018 11:41:37 +0300 Subject: [PATCH 2/6] make linter happy --- lib/cmds/template_generator.js | 19 ++++++++----------- lib/utils/utils.js | 3 +-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/cmds/template_generator.js b/lib/cmds/template_generator.js index 4fc779710..10e99e40a 100644 --- a/lib/cmds/template_generator.js +++ b/lib/cmds/template_generator.js @@ -53,9 +53,6 @@ class TemplateGenerator { } getExternalProject(uri) { - const constants = require('../constants'); - const RAW_URL = 'https://github.com/'; - let match = uri.match( /\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/ ); @@ -63,17 +60,17 @@ class TemplateGenerator { let url, folder; if (uri.startsWith('http')) { - url = uri + "/archive/master.zip" - folder = match[1] + url = uri + "/archive/master.zip"; + folder = match[1]; } else if (uri.startsWith('github')) { - url = "https://" + uri + "/archive/master.zip" - folder = match[1] + url = "https://" + uri + "/archive/master.zip"; + folder = match[1]; } else if (uri.split('/').length === 2) { - url = "https://github.com/" + uri + "/archive/master.zip" - folder = uri + url = "https://github.com/" + uri + "/archive/master.zip"; + folder = uri; } else if (uri.indexOf('/') === -1) { - url = "https://github.com/embark-framework/embark-" + uri + "-template/archive/master.zip" - folder = "embark-framework/embark-" + uri + "-template" + url = "https://github.com/embark-framework/embark-" + uri + "-template/archive/master.zip"; + folder = "embark-framework/embark-" + uri + "-template"; } return { diff --git a/lib/utils/utils.js b/lib/utils/utils.js index b3a2fb38a..143b03ece 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -176,8 +176,7 @@ function extractTar(filename, packageDirectory, cb) { function extractZip(filename, packageDirectory, cb) { const decompress = require('decompress'); - decompress(filename, packageDirectory).then(files => { - console.log('done!'); + decompress(filename, packageDirectory).then((_files) => { cb(); }); } From 440baeb323f8df9ce7859171f65d48b1d4748b74 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 6 Jul 2018 11:52:47 +0300 Subject: [PATCH 3/6] refactor install template code --- lib/cmds/template_generator.js | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/cmds/template_generator.js b/lib/cmds/template_generator.js index 10e99e40a..db2299bed 100644 --- a/lib/cmds/template_generator.js +++ b/lib/cmds/template_generator.js @@ -7,8 +7,10 @@ class TemplateGenerator { } downloadAndGenerate(uri, destinationFolder, name) { + const self = this; let {url, filePath} = this.getExternalProject(uri); let tmpFilePath = fs.tmpDir(filePath); + console.log(__('Installing Template from ' + uri + '....').green); fs.mkdirpSync(utils.dirname(tmpFilePath)); utils.downloadFile(url, tmpFilePath, () => { @@ -22,26 +24,20 @@ class TemplateGenerator { file.path = utils.joinPath(...fixed_path); return file; } + }).then(() => { + self.installTemplate(fspath, name, true); }); }); } generate(destinationFolder, name) { - let templatePath = fs.embarkPath(utils.joinPath('templates', this.templateName)); console.log(__('Initializing Embark Template....').green); + + let templatePath = fs.embarkPath(utils.joinPath('templates', this.templateName)); let fspath = utils.joinPath(destinationFolder, name); - fs.copySync(templatePath, fspath); - utils.cd(fspath); - utils.sed('package.json', '%APP_NAME%', name); - if (name === 'embark_demo') { - console.log(__('Installing packages...').green); - utils.runCmd('npm install'); - } - - console.log(__('Init complete').green); - console.log('\n' + __('App ready at ').green + fspath); + this.installTemplate(fspath, name, (name === 'embark_demo')); if (name === 'embark_demo') { console.log('-------------------'.yellow); @@ -52,6 +48,19 @@ class TemplateGenerator { } } + installTemplate(templatePath, name, installPackages) { + utils.cd(templatePath); + utils.sed('package.json', '%APP_NAME%', name); + + if (installPackages) { + console.log(__('Installing packages...').green); + utils.runCmd('npm install'); + } + + console.log(__('Init complete').green); + console.log('\n' + __('App ready at ').green + templatePath); + } + getExternalProject(uri) { let match = uri.match( /\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/ From a4b95d13d5c348dd420641cf6fd1e8778ad545f5 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 6 Jul 2018 17:54:52 +0300 Subject: [PATCH 4/6] use utils extractZip instead of lib directly --- lib/cmds/template_generator.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cmds/template_generator.js b/lib/cmds/template_generator.js index db2299bed..43d6b1ec8 100644 --- a/lib/cmds/template_generator.js +++ b/lib/cmds/template_generator.js @@ -15,9 +15,8 @@ class TemplateGenerator { fs.mkdirpSync(utils.dirname(tmpFilePath)); utils.downloadFile(url, tmpFilePath, () => { let fspath = utils.joinPath(destinationFolder, name); - const decompress = require('decompress'); - decompress(tmpFilePath, fspath, { + utils.extractZip(tmpFilePath, fspath, { map: file => { let fixed_path = file.path.split('/'); fixed_path.shift(); // remove first directory From c5b10cce17386bb8fb022ec686e3736cfcc8ba1e Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 6 Jul 2018 18:02:25 +0300 Subject: [PATCH 5/6] refactor template test --- test/template.js | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/test/template.js b/test/template.js index b539e7c9c..3e5e252d1 100644 --- a/test/template.js +++ b/test/template.js @@ -12,46 +12,40 @@ describe('TemplateGenerator', function () { describe('with github link', function () { - it('return correct zip filename for https link', function (done) { + it('return correct zip filename for https link', function () { let result = templateGenerator.getExternalProject("https://github.com/embark-framework/embark"); - assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); - assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); - done(); + assert.strictEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.strictEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); }); - it('return correct zip filename for http link', function (done) { + it('return correct zip filename for http link', function () { let result = templateGenerator.getExternalProject("http://github.com/embark-framework/embark"); - assert.deepEqual(result.url, "http://github.com/embark-framework/embark/archive/master.zip"); - assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); - done(); + assert.strictEqual(result.url, "http://github.com/embark-framework/embark/archive/master.zip"); + assert.strictEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); }); - it('return correct zip filename without protocol specified ', function (done) { + it('return correct zip filename without protocol specified ', function () { let result = templateGenerator.getExternalProject("github.com/embark-framework/embark"); - assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); - assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); - done(); + assert.strictEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.strictEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); }); - it('return correct zip filename without protocol specified ', function (done) { + it('return correct zip filename without protocol specified ', function () { let result = templateGenerator.getExternalProject("github.com/embark-framework/embark"); - assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); - assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); - done(); + assert.strictEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.strictEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); }); - it('return correct zip filename with just username/repo specified', function (done) { + it('return correct zip filename with just username/repo specified', function () { let result = templateGenerator.getExternalProject("embark-framework/embark"); - assert.deepEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); - assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); - done(); + assert.strictEqual(result.url, "https://github.com/embark-framework/embark/archive/master.zip"); + assert.strictEqual(result.filePath, ".embark/templates/embark-framework/embark/archive.zip"); }); - it('return correct zip filename with just embark template specified', function (done) { + it('return correct zip filename with just embark template specified', function () { let result = templateGenerator.getExternalProject("react"); - assert.deepEqual(result.url, "https://github.com/embark-framework/embark-react-template/archive/master.zip"); - assert.deepEqual(result.filePath, ".embark/templates/embark-framework/embark-react-template/archive.zip"); - done(); + assert.strictEqual(result.url, "https://github.com/embark-framework/embark-react-template/archive/master.zip"); + assert.strictEqual(result.filePath, ".embark/templates/embark-framework/embark-react-template/archive.zip"); }); }); From 98e61a5cb0292c7abbb6277f8ac62c90a11fef92 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 6 Jul 2018 18:06:55 +0300 Subject: [PATCH 6/6] simplify utils exports --- lib/utils/utils.js | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/utils/utils.js b/lib/utils/utils.js index 143b03ece..62036d19c 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -311,31 +311,31 @@ function buildUrlFromConfig (configObj){ } module.exports = { - joinPath: joinPath, - dirname: dirname, - filesMatchingPattern: filesMatchingPattern, - fileMatchesPattern: fileMatchesPattern, - recursiveMerge: recursiveMerge, - checkIsAvailable: checkIsAvailable, - httpGet: httpGet, - httpsGet: httpsGet, - httpGetJson: httpGetJson, - httpsGetJson: httpsGetJson, - hexToNumber: hexToNumber, + joinPath, + dirname, + filesMatchingPattern, + fileMatchesPattern, + recursiveMerge, + checkIsAvailable, + httpGet, + httpsGet, + httpGetJson, + httpsGetJson, + hexToNumber, pingEndpoint, - decodeParams: decodeParams, - runCmd: runCmd, + decodeParams, + runCmd, cd: cd, sed: sed, exit: exit, - downloadFile: downloadFile, - extractTar: extractTar, - extractZip: extractZip, - proposeAlternative: proposeAlternative, + downloadFile, + extractTar, + extractZip, + proposeAlternative, pwd: pwd, getExternalContractUrl, - toChecksumAddress: toChecksumAddress, - sha3: sha3, + toChecksumAddress, + sha3, normalizeInput, buildUrl, buildUrlFromConfig