Skip to content

Commit

Permalink
Cleaned up code.
Browse files Browse the repository at this point in the history
Moved a lot of code out of the routing-related files and into the util files.
  • Loading branch information
emilrose committed Feb 23, 2016
1 parent 639bde5 commit a8f5ad9
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 117 deletions.
17 changes: 3 additions & 14 deletions mcnode/app/logic/tools/analysis.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
"use strict";
var child_process = require('child_process');

var config = require(__base + 'config/config');
var userfile_utils = require(__base + 'app/logic/util/userfile_utils');
var tool_usage = require(__base + 'app/logic/util/tool_usage');

// Perform kind analysis on the file given in filepath and return the results as JSON
function kindAnalysis(req, res) {
console.log('kind_analysis request');
const sessionID = req.params.sessionID;
const filepath = req.params.filepath;

let pathToFile = userfile_utils.fileInWorkspace(sessionID, filepath);
const command = `java -jar ${config.MCLAB_CORE_JAR_PATH} --json ${pathToFile}`;

child_process.exec(command, function(error, stdout){
try {
let jsonTree = JSON.parse(stdout);
let output = {};
tool_usage.extractKinds(jsonTree, output);
tool_usage.performKindAnalysis(sessionID, filepath, (err, output) =>{
if (!err){
res.json(output);
}
catch(err){
else{
res.status(400).json({msg: 'Mclab-core failed to do kind analysis on this file. Is this a valid matlab file?'});
}
});
Expand Down
85 changes: 5 additions & 80 deletions mcnode/app/logic/tools/compile.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
"use strict";
var path = require('path');
var fs = require('fs');
var child_process = require('child_process');
var underscore = require('underscore');
var async = require('async');

var config = require(__base + 'config/config');
var userfile_utils = require(__base + 'app/logic/util/userfile_utils');
var tool_analysis = require(__base + 'app/logic/util/tool_usage');
var sessions = require(__base + 'app/logic/util/session_utils');
var tool_usage = require(__base + 'app/logic/util/tool_usage');

// Compile the file at given filepath, and with given arguments, to Fortran
// Zip the result and return the path to it
Expand All @@ -18,78 +9,12 @@ function compileToFortran(req, res) {
const sessionID = req.params.sessionID;
const body = req.body;
const mainFile = body.mainFile || '';
let argString;
try{
argString = tool_analysis.buildFortranArgString(body.arg);
}
catch (e){
res.status(400).json({msg: e});
}
const mainFilePath = userfile_utils.fileInWorkspace(sessionID, mainFile); // path to entry point file to be compiled
const mainFileDir = path.dirname(mainFilePath); // directory of this file
const genRootPath = userfile_utils.genRoot(sessionID);
const fortranRootPath = userfile_utils.fortranRoot(sessionID);

const command = `java -jar ${config.MC2FOR_PATH} ${mainFilePath} -args ${argString} -codegen`;

// Compile the files; this will produce Fortran (.f95) files in the same directory as the Matlab files
child_process.exec(command, function(err){
tool_usage.compileToFortran(sessionID, body, mainFile, (err, package_path) => {
if(!err){
// Make a gen folder for the user; if it exists already, just ignore the error
fs.mkdir(genRootPath, function(err){
// Remove the fortran-code subfolder, if it exists, and make a new one
child_process.exec('rm -r ' + fortranRootPath, function (err) {
fs.mkdir(fortranRootPath, function(err){
// Read all the files in the directory where our .f95 files are located
fs.readdir(mainFileDir, function (err, files) {
let fortranFiles = []; // names of the .f95 files
for (let fileInDir of files) {
if (fileInDir.slice(-4) == '.f95') {
fortranFiles.push(fileInDir);
}
}

let fortranFilePathList = []; // paths to the .f95 files
for (let fortranFile of fortranFiles) {
fortranFilePathList.push(path.join(mainFileDir, fortranFile));
}

let finalFilePaths = []; // paths where each .f95 file should end up
for (let fortranFile of fortranFiles) {
finalFilePaths.push(path.join(fortranRootPath, fortranFile))
}

// Hacky way of renaming a list of files asynchronously
let rename = function(index, cb){
fs.rename(fortranFilePathList[index], finalFilePaths[index], function(){
cb();
});
};
var rangeOverFiles = underscore.range(fortranFilePathList.length);
//const zippedFilePaths = underscore.zip(fortranFilePathList, finalFilePaths);
async.each(rangeOverFiles, rename, function(err){
// create a UUID and name for the archive to be created out of these files
const archiveUUID = sessions.createUUID();
const archiveName = `fortran-package-${archiveUUID}`;
const archivePath = path.join(genRootPath, archiveName + '.zip');
const relPathToArchive = path.relative(genRootPath, archivePath);
const package_path = `files/download/${relPathToArchive}`;

// Zip the files and return the path to the zip file (relative to /session, since this is the API call to be made)
child_process.exec(`zip -j ${archivePath} ${fortranRootPath}/*.f95`, function(err){

res.json({
package_path: package_path
});
});
});
});
});
});
});
res.json(package_path);
}
else {
res.status(400).json({msg: 'Failed to compile this project.'});
else{
res.status(400).json(err);
}
});
}
Expand Down
28 changes: 7 additions & 21 deletions mcnode/app/logic/tools/userfiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ var child_process = require('child_process');
var path = require('path');

var config = require(__base + 'config/config');
var AdmZip = require('adm-zip');

var userfile_utils = require(__base + 'app/logic/util/userfile_utils');
var tool_usage = require(__base + 'app/logic/util/tool_usage');
Expand Down Expand Up @@ -32,26 +31,13 @@ function upload(req, res) {
if (req.files) {
// Grab the file and the path to the user's directory
const file = req.files[0];
const userRoot = userfile_utils.userRoot(sessionID);

// Create the user directory; if it already exists, does nothing, and we just ignore the error
fs.mkdir(userRoot, function(){
const pathToZip = path.join(userRoot, file.fieldname);
// Attempt to write the zip file to the user's root
fs.writeFile(pathToZip, file.buffer, function(err){
if(err){
console.log("write failed");
console.log(err);
res.status(400).json({msg: 'Write failed'});
}
else{
// Extract the files in the zip to the user's workspace
const pathToUnzippedFiles = userfile_utils.userWorkspace(sessionID);
let zip = new AdmZip(pathToZip);
zip.extractAllTo(pathToUnzippedFiles);
res.send('');
}
});
userfile_utils.uploadFile(file, sessionID, function(err){
if(!err){
res.send('');
}
else{
res.status(400).json({msg: 'Write failed'});
}
});
}
else{
Expand Down
105 changes: 104 additions & 1 deletion mcnode/app/logic/util/tool_usage.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
"use strict";
var child_process = require('child_process');
var path = require('path');
var fs = require('fs');

var config = require(__base + 'config/config');
var userfile_utils = require(__base + 'app/logic/util/userfile_utils');
var sessions = require(__base + 'app/logic/util/session_utils');

var underscore = require('underscore');
var async = require('async');

// Take a jsonSubtree object representing the output (or part of the output) of McLabCore kind analysis
// 'output' is mutated through the function; may want to make this function pure instead
Expand Down Expand Up @@ -33,6 +43,23 @@ function extractKinds(jsonSubtree, output){
}
}

function performKindAnalysis(sessionID, filepath, cb){
let pathToFile = userfile_utils.fileInWorkspace(sessionID, filepath);
const command = `java -jar ${config.MCLAB_CORE_JAR_PATH} --json ${pathToFile}`;

child_process.exec(command, (error, stdout) =>{
try {
let jsonTree = JSON.parse(stdout);
let output = {};
this.extractKinds(jsonTree, output);
cb(null, output);
}
catch(err){
cb("Could not do kind analysis", null)
}
});
}

// Takes object representing Mc2For command line arguments; returns a formatted argument string.
// Throws an exception if the arguments are not valid; the compilation would fail anyways, but this protects us against
// an injection attack.
Expand Down Expand Up @@ -71,7 +98,83 @@ function validateArgs(mlClass, numRows, numCols, realComplex){
return true;
}

function compileToFortran(sessionID, body, mainFile, cb){
let argString;
try{
argString = this.buildFortranArgString(body.arg);
}
catch (e){
cb({msg: e}, null);
}
const mainFilePath = userfile_utils.fileInWorkspace(sessionID, mainFile); // path to entry point file to be compiled
const mainFileDir = path.dirname(mainFilePath); // directory of this file
const genRootPath = userfile_utils.genRoot(sessionID);
const fortranRootPath = userfile_utils.fortranRoot(sessionID);

const command = `java -jar ${config.MC2FOR_PATH} ${mainFilePath} -args ${argString} -codegen`;

// Compile the files; this will produce Fortran (.f95) files in the same directory as the Matlab files
child_process.exec(command, function(err){
if(!err){
// Make a gen folder for the user; if it exists already, just ignore the error
fs.mkdir(genRootPath, function(err){
// Remove the fortran-code subfolder, if it exists, and make a new one
child_process.exec('rm -r ' + fortranRootPath, function (err) {
fs.mkdir(fortranRootPath, function(err){
// Read all the files in the directory where our .f95 files are located
fs.readdir(mainFileDir, function (err, files) {
let fortranFiles = []; // names of the .f95 files
for (let fileInDir of files) {
if (fileInDir.slice(-4) == '.f95') {
fortranFiles.push(fileInDir);
}
}

let fortranFilePathList = []; // paths to the .f95 files
for (let fortranFile of fortranFiles) {
fortranFilePathList.push(path.join(mainFileDir, fortranFile));
}

let finalFilePaths = []; // paths where each .f95 file should end up
for (let fortranFile of fortranFiles) {
finalFilePaths.push(path.join(fortranRootPath, fortranFile))
}

// Hacky way of renaming a list of files asynchronously
let rename = function(index, cb){
fs.rename(fortranFilePathList[index], finalFilePaths[index], function(){
cb();
});
};
var rangeOverFiles = underscore.range(fortranFilePathList.length);
//const zippedFilePaths = underscore.zip(fortranFilePathList, finalFilePaths);
async.each(rangeOverFiles, rename, function(err){
// create a UUID and name for the archive to be created out of these files
const archiveUUID = sessions.createUUID();
const archiveName = `fortran-package-${archiveUUID}`;
const archivePath = path.join(genRootPath, archiveName + '.zip');
const relPathToArchive = path.relative(genRootPath, archivePath);
const package_path = `files/download/${relPathToArchive}`;

// Zip the files and return the path to the zip file (relative to /session, since this is the API call to be made)
child_process.exec(`zip -j ${archivePath} ${fortranRootPath}/*.f95`, function(err){
cb(null, {package_path: package_path});
});
});
});
});
});
});
}
else {
cb({msg: 'Failed to compile this project.'}, null);
}
});
}

module.exports = {
extractKinds,
buildFortranArgString
performKindAnalysis,
buildFortranArgString,
compileToFortran
};
30 changes: 29 additions & 1 deletion mcnode/app/logic/util/userfile_utils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"use strict";
var path = require('path');
var fs = require('fs');

var config = require(__base + 'config/config');
var async = require('async');
var underscore = require('underscore');
var AdmZip = require('adm-zip');


// McLab-Web/user-files/{sessionID}
function userRoot(sessionID){
Expand Down Expand Up @@ -93,12 +96,37 @@ function createFileTree(startPath, dirPath, cb){
});
}

function uploadFile(file, sessionID, cb){
const userRoot = this.userRoot(sessionID);

// Create the user directory; if it already exists, does nothing, and we just ignore the error
fs.mkdir(userRoot, () => {
const pathToZip = path.join(userRoot, file.fieldname);
// Attempt to write the zip file to the user's root
fs.writeFile(pathToZip, file.buffer, (err) =>{
if(err){
console.log("write failed");
console.log(err);
cb({Message: "Write failed"});
}
else{
// Extract the files in the zip to the user's workspace
const pathToUnzippedFiles = this.userWorkspace(sessionID);
let zip = new AdmZip(pathToZip);
zip.extractAllTo(pathToUnzippedFiles);
cb(null);
}
});
});
}

module.exports = {
userRoot,
userWorkspace,
fileInWorkspace,
fileInGen,
genRoot,
fortranRoot,
createFileTree
createFileTree,
uploadFile
};

0 comments on commit a8f5ad9

Please sign in to comment.