From ce68ca6ff92e5a3d0c8bf47356070c53c7aef3c4 Mon Sep 17 00:00:00 2001 From: Jeremiah Harlan Date: Wed, 13 Jan 2016 14:53:02 -0500 Subject: [PATCH 1/6] Add librarian call to api to get project source --- lib/librarian/librarian.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/librarian/librarian.js b/lib/librarian/librarian.js index 58c1fcf..d76cd77 100755 --- a/lib/librarian/librarian.js +++ b/lib/librarian/librarian.js @@ -406,6 +406,13 @@ librarian.project.scale = function(projectId, instances, authToken, callback) { } }; +//----------------------------------------------------------------------------- +librarian.project.download = function(projectId, authToken, callback) { + if(checkInit(callback)) { + librarian._http.raw(util.format('/project/%s/download?authToken=%s', projectId, authToken), 'GET', callback); + } +}; + //----------------------------------------------------------------------------- // ADDONS //----------------------------------------------------------------------------- From e85c3065a2aebba0efc3004ef791bcbb4edd60ec Mon Sep 17 00:00:00 2001 From: Jeremiah Harlan Date: Wed, 13 Jan 2016 14:57:36 -0500 Subject: [PATCH 2/6] Add feature to download latest deployed source code from API Add flags to specify zip name when downloading source code. --- lib/commands/project.js | 51 ++++++++++++++++++++++++++++++++++++++ lib/controllers/project.js | 41 ++++++++++++++++++++++++++++++ lib/routes/project.js | 28 +++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/lib/commands/project.js b/lib/commands/project.js index 4f0d6c2..7f7b5fb 100755 --- a/lib/commands/project.js +++ b/lib/commands/project.js @@ -1040,6 +1040,57 @@ project.getMainFile = function(cb) { cb('Main file not specified in package.json.'); } } + +//----------------------------------------------------------------------------- +/** + * Description - Downloads the source code for a specific project. + * @param {string} projectName - name of the project to retrieve logs from. + * @param {string} output - filename to download the tarball at + * @param {string} dir - directory to download to + * @param {function} cb Callback invoked with log data. + */ +//----------------------------------------------------------------------------- +project.download = function (projectName, output, dir, cb) { + if (typeof dir !== 'string') { + dir = process.cwd(); + } + dir = path.resolve(dir); + dir = dir.replace(/\\/g, '/'); + if (!fs.existsSync(dir)) { + return cb('Directory "' + dir + '" does not exist.'); + } + + projectController.find({ + userId : userConfig.data.userId + }, + function (err, projects) { + if (err) { + err = error.handleApiError(err, 'GET_PROJECT_SOURCE', cb); + if (err.length > 0) return cb(err); + } + + if (projects.length === 0) { + modulus.io.error('You currently have no projects. You can create one with "project create".'); + return cb(); + } + + project.chooseProjectPrompt(projects, projectName, function (err, result) { + if (err) return cb(err); + if (!result) return cb('You must select a project.'); + if (result.status === 'NONE') return cb('You must deploy to your project in order to download the source.'); + + projectController.download(result.id, result.name, output, function (err, res) { + if (!err) { + modulus.io.success(res.msg); + } else { + modulus.io.error('Problem downloading logs.'); + } + + cb(); + }); + }); + } + ); }; //------------------------------------------------------------------------------------------------- diff --git a/lib/controllers/project.js b/lib/controllers/project.js index 4e05bee..affb17b 100755 --- a/lib/controllers/project.js +++ b/lib/controllers/project.js @@ -588,6 +588,47 @@ Project.prototype.scale = function (projectId, instances, await, callback) { }); }; +/** + * Downloads the source code as a tarball for the specified project id. + * @param {string} projectId - the ID of the project. + * @param {string} projectName - the name of the project + * @param {string} outLocation - the path to the directory where the tarball should be downloaded + * @param {function} callback - function invoked with the file stream. Responsible for the actual download. + */ +//----------------------------------------------------------------------------- +Project.prototype.download = function(projectId, projectName, outLocation, callback) { + librarian.project.download(projectId, userConfig.data.apiKey, function (err, req, res) { + if (err) return callback(Errors.getMessage(err)); + + + var date = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''); + var outFile = projectName + '_' + date + '.zip'; + + if (typeof outLocation === 'string') { + outFile = outLocation; + outFile = outFile.replace(/\//g, '/'); + + if (!fs.existsSync(path.dirname(outLocation))) return callback('Directory ' + path.dirname(outLocation) + ' does not exist.'); + } + + var dir = path.dirname(outLocation) === '.' ? process.cwd() : path.dirname(path.resolve(outLocation)); + outFile = outFile.replace(/ /g, '_').replace(/:/g,'.').replace(/[[\]{}@~`<>()*+=%&!?,\\^$|#\s]/g,''); + + var result = {}; + var stream = fs.createWriteStream(outFile); + + res.pipe(stream).on('finish', function (err, stdout, stderr) { + if (err) return callback(Errors.getMessage(err)); + if (stderr) result.stderr = stderr; + if (stdout) result.stdout = stdout; + + result.msg = path.basename(outFile) + ' downloaded to ' + dir + '.'; + result.outFile = outFile; + callback(null, result); + }); + }); +}; + //----------------------------------------------------------------------------- /** * Detects the type of project being deployed. diff --git a/lib/routes/project.js b/lib/routes/project.js index d5a039c..b2e462f 100755 --- a/lib/routes/project.js +++ b/lib/routes/project.js @@ -233,6 +233,17 @@ module.exports = function (modulus) { true); }; + var downloadHandler = function (dir) { + modulus.runCommand( + modulus.commands.project.download, + [ + modulus.program.projectName, + modulus.program.output, + dir + ], + true); + }; + modulus.program .command('project logs') .description('Gets logs for the selected project.') @@ -354,6 +365,23 @@ module.exports = function (modulus) { modulus.runCommand(modulus.commands.project.runApp, [modulus.program.projectName, modulus.program.nodeEnv], true); }); + help.add('download', function () { + this.line('project download'.verbose); + this.line('Gets source for the selected project.'.input); + this.line(' options:'.input); + this.line(' -p, --project-name Name of the project to retrieve logs from. Prompts are skipped when specified.'.input); + this.line(' -o, --output Specifies the file to download to. Must be file type zip'.input); + this.line(''); + }); + + modulus.program + .command('project download') + .description('Gets source for the selected project.') + .on('--help', function () { + help.commands.download(); + }) + .action(downloadHandler); + // Generic help for project commands modulus.program .command('project') From 2321a413bf8f65a74c97745c224828b2cb0f8eba Mon Sep 17 00:00:00 2001 From: Jeremiah Harlan Date: Thu, 14 Jan 2016 09:09:29 -0500 Subject: [PATCH 3/6] Fix print message on failure to download source code --- lib/commands/project.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/commands/project.js b/lib/commands/project.js index 7f7b5fb..e0d16c1 100755 --- a/lib/commands/project.js +++ b/lib/commands/project.js @@ -1051,14 +1051,12 @@ project.getMainFile = function(cb) { */ //----------------------------------------------------------------------------- project.download = function (projectName, output, dir, cb) { - if (typeof dir !== 'string') { - dir = process.cwd(); - } + if (typeof dir !== 'string') dir = process.cwd(); + dir = path.resolve(dir); dir = dir.replace(/\\/g, '/'); - if (!fs.existsSync(dir)) { - return cb('Directory "' + dir + '" does not exist.'); - } + + if (!fs.existsSync(dir)) return cb('Directory "' + dir + '" does not exist.'); projectController.find({ userId : userConfig.data.userId @@ -1083,7 +1081,7 @@ project.download = function (projectName, output, dir, cb) { if (!err) { modulus.io.success(res.msg); } else { - modulus.io.error('Problem downloading logs.'); + modulus.io.error('Problem downloading source.'); } cb(); From 69d0c4c6254b34f7a3e304b579bf490a4c0b7376 Mon Sep 17 00:00:00 2001 From: Jeremiah Harlan Date: Thu, 14 Jan 2016 17:19:14 -0500 Subject: [PATCH 4/6] Check to ensure outLocation has `.zip` at the end of string If outLocation does not have `.zip` at the end of the string then append it --- lib/commands/project.js | 10 +--------- lib/controllers/project.js | 1 + 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/commands/project.js b/lib/commands/project.js index e0d16c1..25f0f14 100755 --- a/lib/commands/project.js +++ b/lib/commands/project.js @@ -1046,18 +1046,10 @@ project.getMainFile = function(cb) { * Description - Downloads the source code for a specific project. * @param {string} projectName - name of the project to retrieve logs from. * @param {string} output - filename to download the tarball at - * @param {string} dir - directory to download to * @param {function} cb Callback invoked with log data. */ //----------------------------------------------------------------------------- -project.download = function (projectName, output, dir, cb) { - if (typeof dir !== 'string') dir = process.cwd(); - - dir = path.resolve(dir); - dir = dir.replace(/\\/g, '/'); - - if (!fs.existsSync(dir)) return cb('Directory "' + dir + '" does not exist.'); - +project.download = function (projectName, output, cb) { projectController.find({ userId : userConfig.data.userId }, diff --git a/lib/controllers/project.js b/lib/controllers/project.js index affb17b..99bd737 100755 --- a/lib/controllers/project.js +++ b/lib/controllers/project.js @@ -607,6 +607,7 @@ Project.prototype.download = function(projectId, projectName, outLocation, callb if (typeof outLocation === 'string') { outFile = outLocation; outFile = outFile.replace(/\//g, '/'); + if (outFile.substring(outFile.length-4) !== '.zip') outFile += '.zip'; if (!fs.existsSync(path.dirname(outLocation))) return callback('Directory ' + path.dirname(outLocation) + ' does not exist.'); } From 0e91d93d58ce34fe2e1a7d242e88c22da4b2d54b Mon Sep 17 00:00:00 2001 From: Jeremiah Harlan Date: Thu, 14 Jan 2016 17:20:20 -0500 Subject: [PATCH 5/6] Remove `dir` from `downloadHandler` and in project command file --- lib/routes/project.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/routes/project.js b/lib/routes/project.js index b2e462f..7ad9d45 100755 --- a/lib/routes/project.js +++ b/lib/routes/project.js @@ -233,17 +233,6 @@ module.exports = function (modulus) { true); }; - var downloadHandler = function (dir) { - modulus.runCommand( - modulus.commands.project.download, - [ - modulus.program.projectName, - modulus.program.output, - dir - ], - true); - }; - modulus.program .command('project logs') .description('Gets logs for the selected project.') @@ -380,7 +369,10 @@ module.exports = function (modulus) { .on('--help', function () { help.commands.download(); }) - .action(downloadHandler); + .action(function () { + modulus.runCommand( + modulus.commands.project.download, [modulus.program.projectName, modulus.program.output], true); + }); // Generic help for project commands modulus.program From 31b7b9972df2c4ecde5e61f85f78924e620f40c6 Mon Sep 17 00:00:00 2001 From: Jeremiah Harlan Date: Mon, 18 Jan 2016 11:46:31 -0500 Subject: [PATCH 6/6] Lint code --- lib/commands/project.js | 12 ++++++------ lib/controllers/project.js | 22 +++++++++++++--------- lib/librarian/librarian.js | 7 ++++--- lib/routes/project.js | 5 ++++- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/commands/project.js b/lib/commands/project.js index 25f0f14..89a9005 100755 --- a/lib/commands/project.js +++ b/lib/commands/project.js @@ -951,7 +951,6 @@ project.scale = function (instances, projectName, cb) { //-------------------------------------------------------------------- project.runApp = function(projectName, nodeEnv, cb) { - console.log(arguments); async.waterfall([ function getUserProjects (fn) { projectController.find({ userId: userConfig.data.userId }, function (err, projects) { @@ -1040,6 +1039,7 @@ project.getMainFile = function(cb) { cb('Main file not specified in package.json.'); } } +}; //----------------------------------------------------------------------------- /** @@ -1048,10 +1048,10 @@ project.getMainFile = function(cb) { * @param {string} output - filename to download the tarball at * @param {function} cb Callback invoked with log data. */ -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- project.download = function (projectName, output, cb) { projectController.find({ - userId : userConfig.data.userId + userId: userConfig.data.userId }, function (err, projects) { if (err) { @@ -1070,12 +1070,12 @@ project.download = function (projectName, output, cb) { if (result.status === 'NONE') return cb('You must deploy to your project in order to download the source.'); projectController.download(result.id, result.name, output, function (err, res) { - if (!err) { - modulus.io.success(res.msg); - } else { + if (err) { modulus.io.error('Problem downloading source.'); + return cb(); } + modulus.io.success(res.msg); cb(); }); }); diff --git a/lib/controllers/project.js b/lib/controllers/project.js index 99bd737..69ea133 100755 --- a/lib/controllers/project.js +++ b/lib/controllers/project.js @@ -588,6 +588,7 @@ Project.prototype.scale = function (projectId, instances, await, callback) { }); }; +// ----------------------------------------------------------------------------- /** * Downloads the source code as a tarball for the specified project id. * @param {string} projectId - the ID of the project. @@ -595,28 +596,31 @@ Project.prototype.scale = function (projectId, instances, await, callback) { * @param {string} outLocation - the path to the directory where the tarball should be downloaded * @param {function} callback - function invoked with the file stream. Responsible for the actual download. */ -//----------------------------------------------------------------------------- -Project.prototype.download = function(projectId, projectName, outLocation, callback) { +// ----------------------------------------------------------------------------- +Project.prototype.download = function (projectId, projectName, outLocation, callback) { librarian.project.download(projectId, userConfig.data.apiKey, function (err, req, res) { - if (err) return callback(Errors.getMessage(err)); + var message, date, outFile, dir, stream, result = {}; + if (err) return callback(Errors.getMessage(err)); - var date = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''); - var outFile = projectName + '_' + date + '.zip'; + date = new Date().toISOString().replace(/:/g, '.'); + outFile = projectName + '_' + date + '.zip'; if (typeof outLocation === 'string') { outFile = outLocation; outFile = outFile.replace(/\//g, '/'); if (outFile.substring(outFile.length-4) !== '.zip') outFile += '.zip'; - if (!fs.existsSync(path.dirname(outLocation))) return callback('Directory ' + path.dirname(outLocation) + ' does not exist.'); + message = 'Directory ' + path.dirname(outLocation) + ' does not exist.'; + if (!fs.existsSync(path.dirname(outLocation))) return callback(message); } - var dir = path.dirname(outLocation) === '.' ? process.cwd() : path.dirname(path.resolve(outLocation)); + if (path.dirname(outLocation) === '.') dir = process.cwd(); + else dir = path.dirname(path.resolve(outLocation)); + outFile = outFile.replace(/ /g, '_').replace(/:/g,'.').replace(/[[\]{}@~`<>()*+=%&!?,\\^$|#\s]/g,''); - var result = {}; - var stream = fs.createWriteStream(outFile); + stream = fs.createWriteStream(outFile); res.pipe(stream).on('finish', function (err, stdout, stderr) { if (err) return callback(Errors.getMessage(err)); diff --git a/lib/librarian/librarian.js b/lib/librarian/librarian.js index d76cd77..ce37ea4 100755 --- a/lib/librarian/librarian.js +++ b/lib/librarian/librarian.js @@ -407,9 +407,10 @@ librarian.project.scale = function(projectId, instances, authToken, callback) { }; //----------------------------------------------------------------------------- -librarian.project.download = function(projectId, authToken, callback) { - if(checkInit(callback)) { - librarian._http.raw(util.format('/project/%s/download?authToken=%s', projectId, authToken), 'GET', callback); +librarian.project.download = function (projectId, authToken, callback) { + var route = '/project/%s/download?authToken=%s'; + if (checkInit(callback)) { + librarian._http.raw(util.format(route, projectId, authToken), 'GET', callback); } }; diff --git a/lib/routes/project.js b/lib/routes/project.js index 7ad9d45..8327a29 100755 --- a/lib/routes/project.js +++ b/lib/routes/project.js @@ -371,7 +371,10 @@ module.exports = function (modulus) { }) .action(function () { modulus.runCommand( - modulus.commands.project.download, [modulus.program.projectName, modulus.program.output], true); + modulus.commands.project.download, + [modulus.program.projectName, modulus.program.output], + true + ); }); // Generic help for project commands