From ee81b7e2099c6a78cb36144185c1b587b140a29d Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 6 Jul 2018 11:38:09 +0300 Subject: [PATCH] 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(); + }); + + }); + + }); +}); +