stpettersens/nodeGaudi

View on GitHub
lib/NodeGaudiBuilder.js

Summary

Maintainability
A
3 hrs
Test Coverage
/**
nodeGaudi platform agnostic build tool.
Copyright 2014 Sam Saint-Pettersen.

Gaudi implemented with Node.js

Released under the MIT/X11 License.
Please see LICENSE file.

@file Builder for NodeGaudi.
@author Sam Saint-Pettersen
@copyright (c) 2014 Sam Saint-Pettersen
@version 1.0.0
*/

// Internal includes.
var habitat = require('./NodeGaudiHabitat.js');

// Node.js standard and module includes.
var fs = require('fs');
var g = require('generic-functions');
var execSync = require('exec-sync');
var colors = require('colors/safe');
var ncp = require('ncp').ncp;
var now = require('performance-now');

var NodeGaudiBuilder = exports;
var self = {};
self.target = "";
self.actionName = "";
self.verbose = true;
self.passed = false;
self.action_start = 0;

/**
 * @global
 * @name NodeGaudiBuilder_init
 * @function
 * @description Initiator for NodeGaudiBuilder.
 * @param {string} actionName Name of action to set.
 * @param {boolean} verbose If true: display all action commands to console.
*/
NodeGaudiBuilder.init = function(actionName, verbose) {
    self.actionName = actionName;
    self.verbose = verbose;
};

/**
 * @global
 * @name NodeGaudiBuilder_setTarget
 * @function
 * @description Set target for the action.
 * @param {string} target Target to build.
*/
NodeGaudiBuilder.setTarget = function(target) {
    self.target = target;
};

/**
 * @global
 * @name NodeGaudiBuilder_doAction
 * @function 
 * @description Set and execute an action.
 * @param {string} action Action to execute.
*/
NodeGaudiBuilder.doAction = function(action) {
    self.action_start = now();
    g.println(colors.yellow("[ " + self.target + " => " + self.actionName + " ]"));
    for(var i = 0; i < action.length; i++) {
        var command = action[i];
        for(var key in command) {
            if(command.hasOwnProperty(key)) {
                doCommand(key, command[key]);
            }
        }
    }
    var time = calculateActionTime(now());
    g.println(colors.green("\nSUCCESSFUL in " + time)); // !
};

/**
 * Calculate time to success or fail for a performed action.
 * @param {integer} end Integer time value.
 * @returns {string} time Time action took to finish or fail.
*/
function calculateActionTime(end) {
    var units = ' ms.';
    var time = end - self.action_start;
    var ftime = time;
    if(time >= 1000) { ftime = (time / 1000) % 60; units = ' s.'; }
    return ftime.toFixed(2) + units + '\n';
}

/**
 * Execute a command in the action.
 * @param {string} command Command to execute.
 * @param {string} param Parameter(s) for command.
*/
function doCommand(command, param) {
    printCommand(command, param);
    switch(command) {
        case "doAction":
            execExtern("./nodeGaudi " + param);
            break;
        case "exec":
            execExtern(param);
            break;
        case "pwd":
            g.println(colors.cyan("\t~ CWD: " + process.cwd()));
            break;
        case "chdir":
            changeDirectory(param);
            break;
        case "mkdir":
            makeDirectory(param);
            break;
        case "list":
            // TODO
            break;
        case "erase":
            eraseFile(param, false);
            break;
        case "erasex":
            eraseFile(param, true);
            break;
        case "append":
            var fileMsg = param.split(">>");
            writeToFile(fileMsg[0], fileMsg[1], true);
            break;
        case "xstrip":
            if(habitat.getOSFamily() === 0) {
                param += ".exe";
            }
            execExtern("strip " + param);
            break;
        case "cat":
            concaternateFile(param);
            break;
        case "copy":
            var srcDest = param.split("->");
            copyFileOrDir(srcDest[0], srcDest[1]);
            break;
        case "mkdir":
            makeDirectory(param);
            break;
    }
}

/**
 * Print and error related to action or command and then exit.
 * @param {string} error Error message.
*/
function printError(error) {
    g.println(colors.red(error + "."));
    var time = calculateActionTime(now());
    g.println(colors.red("\nFAILED in " + time)); // !
    process.exit(-1);
}

/**
 * Print executed command.
 * @param {string} command Command to execute.
 * @param {string} param Parameter(s) for command.
*/
function printCommand(command, param) {
    if(self.verbose && !g.strcmp(command, "echo") && !g.strcmp(command, "null"))
        { g.println(colors.yellow("\t:" + command) + colors.yellow(" " + param)); }
    else if(g.strcmp(command, "echo"))
        { g.println(colors.green("\t# " + param)); }
}

/**
 * Execute an external program or process.
 * @param {string} param Parameter (i.e. executable) to run.
*/
function execExtern(param) {
    var p = execSync(param, true);
    if(p.stderr !== '') { printError(p.stderr); }
    if(p.stdout !== '' && self.verbose) { g.printlns(
    [colors.gray("------------------------------------------------------------"),
    , colors.white(p.stdout),
    colors.gray("------------------------------------------------------------")]); }
}

/**
 * Erase a file.
 * @param {string} file File to erase.
 * @param {boolean} executable If true: file is executable.
 */
function eraseFile(file, executable) {
    //g.println(habitat.getOSFamily());
    if(fs.lstatSync(file).isFile()) {
        try {
            if(executable && habitat.getOSFamily() === 0) {
                fs.unlinkSync(file + ".exe");
            }
            else if(habitat.getOSFamily() === 1 || habitat.getOSFamily() === 2) {
                fs.unlinkSync(file);
            }
        }
        catch(err) {
            printError("Error erasing file: " + file);
        }
    }
    else if(fs.lstatSync(file).isDirectory()) {
        try {
            fs.rmdirSync(file);
        }
        catch(err) {
            printError("Error erasing directory: " + file);
        }
    }
    else { printError("Error erasing: " + file); }
}

/** 
 * Concaternate a file.
 * @param {string} file File to concaternate to console.
*/
function concaternateFile(file) {
    g.println("\n");
    fs.readFileSync(file).toString().split(/\r?\n/).forEach(function(line) {
        g.println(line);
    });
}

/**
  * File writing operations.
  * @param {string} file File to write to.
  * @param {string} message Message to write to file.
  * @param {boolean} append If true: append to existing file.
 */
function writeToFile(file, message, append) {
    if(!append) { fs.writeFileSync(file, message + "\n"); }
    else { fs.appendFileSync(file, message + "\n"); }
}

/**
 * Copy a file or directory.
 * @param {string} src Original file/directory location.
 * @param {string} dest Copy destination.
*/
function copyFileOrDir(src, dest) {
    ncp.limit = 16;
    ncp(src, dest, function(err) {
        if(err) { printError("Problem copying file or directory: " + src); }
    });
}

/**
 * Change working directory.
 * @param {string} dir Directory to change into.
*/
function changeDirectory(dir) {
    try {
        process.chdir(dir);
        g.println(colors.cyan("\t~ CWD: " + process.cwd()));
    }
    catch(err) {
        printError("Problem changing directory:\n" + dir);
    }
}

/**
 * Make a directory.
 * @param {string} dir Directory to create.
*/
function makeDirectory(dir) {
    try {
        fs.mkdirSync(dir);
    }
    catch(err) {
        printError("Problem creating directory: " + dir);
    }
}