<commit_before>#!/usr/bin/env node

const shell = require('shelljs');
const fs = require('fs');
const reqCwd = require('req-cwd');
const path = require('path');
const childprocess = require('child_process');
const istanbul = require('istanbul');
const getInstrumentedVersion = require('./../lib/instrumentSolidity.js');
const CoverageMap = require('./../lib/coverageMap.js');

const istanbulCollector = new istanbul.Collector();
const istanbulReporter = new istanbul.Reporter();

// Very high gas block limits / contract deployment limits
const gasLimitString = '0xfffffffffff';
const gasLimitHex = 0xfffffffffff;
const gasPriceHex = 0x01;

const coverage = new CoverageMap();

// Paths
const coverageDir = './coverageEnv';        // Env that instrumented .sols are tested in

// Options
let coverageOption = '--network coverage';  // Default truffle network execution flag
let silence = '';                           // Default log level: configurable by --silence
let log = console.log;

let testrpcProcess;                         // ref to testrpc server we need to close on exit
let events;                                 // ref to string loaded from 'allFiredEvents'
let testsErrored = null;                    // flag set to non-null if truffle tests error

// --------------------------------------- Utilities -----------------------------------------------
/**
 * Removes coverage build artifacts, kills testrpc.
 * Exits (1) and prints msg on error, exits (0) otherwise.
 * @param  {String} err error message
 */
function cleanUp(err) {
  log('Cleaning up...');
  shell.config.silent = true;
  shell.rm('-Rf', `${coverageDir}`);
  shell.rm('./allFiredEvents');
  shell.rm('./scTopics');
  if (testrpcProcess) { testrpcProcess.kill(); }

  if (err) {
    log(`${err}\nExiting without generating coverage...`);
    process.exit(1);
  } else if (testsErrored) {
    log('Some truffle tests failed while running coverage');
    process.exit(1);
  } else {
    process.exit(0);
  }
}
// --------------------------------------- Script --------------------------------------------------
const config = reqCwd.silent('./.solcover.js') || {};

const workingDir = config.dir || '.';       // Relative path to contracts folder
let port = config.port || 8555;             // Port testrpc listens on
const accounts = config.accounts || 35;     // Number of accounts to testrpc launches with
const copyNodeModules = config.copyNodeModules || false; // Whether we copy node_modules when making coverage environment

// Silence shell and script logging (for solcover's unit tests / CI)
if (config.silent) {
  silence = '> /dev/null 2>&1';
  log = () => {};
}

// Generate a copy of the target project configured for solcover and save to the coverage
// environment folder.
log('Generating coverage environment');
try {
  let files = shell.ls(workingDir);
  const nmIndex = files.indexOf('node_modules');

  if (!config.copyNodeModules && nmIndex > -1) {
    files.splice(nmIndex, 1); // Removes node_modules from array.
  }

  files = files.map(file => `${workingDir}/` + file);
  shell.mkdir(coverageDir);
  shell.cp('-R', files, coverageDir);

  const truffleConfig = reqCwd.silent(`${workingDir}/truffle.js`);

  // Coverage network opts specified: use port if declared
  if (truffleConfig && truffleConfig.networks && truffleConfig.networks.coverage) {
    port = truffleConfig.networks.coverage.port || port;

  // Coverage network opts NOT specified: default to the development network w/ modified
  // port, gasLimit, gasPrice. Export the config object only.
  } else {
    const trufflejs = `
      module.exports = {
        networks: {
          development: {
            host: "localhost",
            network_id: "*",
            port: ${port},
            gas: ${gasLimitHex},
            gasPrice: ${gasPriceHex}
          }
        }
      };`;

    coverageOption = '';
    fs.writeFileSync(`${coverageDir}/truffle.js`, trufflejs);
  }
} catch (err) {
  const msg = ('There was a problem generating the coverage environment: ');
  cleanUp(msg + err);
}

// For each contract except migrations.sol:
// 1. Generate file path reference for coverage report
// 2. Load contract as string
// 3. Instrument contract
// 4. Save instrumented contract in the coverage environment folder where covered tests will run
// 5. Add instrumentation info to the coverage map
let currentFile;
try {
  shell.ls(`${coverageDir}/contracts/**/*.sol`).forEach(file => {
    const migrations = `${coverageDir}/contracts/Migrations.sol`;

    if (file !== migrations) {
      log('Instrumenting ', file);
      currentFile = file;

      const contractPath = path.resolve(file);
      const canonicalPath = contractPath.split('/coverageEnv').join('');
      const contract = fs.readFileSync(contractPath).toString();
      const instrumentedContractInfo = getInstrumentedVersion(contract, canonicalPath);
      fs.writeFileSync(contractPath, instrumentedContractInfo.contract);
      coverage.addContract(instrumentedContractInfo, canonicalPath);
    }
  });
} catch (err) {
  const msg = (`There was a problem instrumenting ${currentFile}: `);
  cleanUp(msg + err);
}

// Run modified testrpc with large block limit, on (hopefully) unused port.
// (Changes here should be also be added to the before() block of test/run.js).
if (!config.norpc) {
  const defaultRpcOptions = `--gasLimit ${gasLimitString} --accounts ${accounts} --port ${port}`;
  const testrpcOptions = config.testrpcOptions || defaultRpcOptions;
  const command = './node_modules/.bin/testrpc-sc ';

  testrpcProcess = childprocess.exec(command + testrpcOptions, null, err => {
    if (err) cleanUp('testRpc errored after launching as a childprocess.');
  });
  log(`Launching testrpc on port ${port}`);
}

// Run truffle (or config.testCommand) over instrumented contracts in the
// coverage environment folder. Shell cd command needs to be invoked
// as its own statement for command line options to work, apparently.
try {
  log('Launching test command (this can take a few seconds)...');
  const defaultCommand = `truffle test ${coverageOption} ${silence}`;
  const command = config.testCommand || defaultCommand;
  shell.cd('./coverageEnv');
  shell.exec(command);
  testsErrored = shell.error();
  shell.cd('./..');
} catch (err) {
  cleanUp(err);
}

// Get events fired during instrumented contracts execution.
try {
  events = fs.readFileSync('./allFiredEvents').toString().split('\n');
  events.pop();
} catch (err) {
  const msg =
  `
    There was an error generating coverage. Possible reasons include:
    1. Another application is using port ${port}
    2. Truffle crashed because your tests errored

  `;
  cleanUp(msg + err);
}

// Generate coverage / write coverage report / run istanbul
try {
  coverage.generate(events, './contracts');

  const json = JSON.stringify(coverage.coverage);
  fs.writeFileSync('./coverage.json', json);

  istanbulCollector.add(coverage.coverage);
  istanbulReporter.add('html');
  istanbulReporter.add('lcov');
  istanbulReporter.add('text');
  istanbulReporter.write(istanbulCollector, true);
} catch (err) {
  if (config.testing) {
    cleanUp();
  } else {
    const msg = 'There was a problem generating producing the coverage map / running Istanbul.\n';
    cleanUp(msg + err);
  }
}

// Finish
cleanUp();
<commit_msg>Change testrpc path for yarn compatibility<commit_after>#!/usr/bin/env node

const shell = require('shelljs');
const fs = require('fs');
const reqCwd = require('req-cwd');
const path = require('path');
const childprocess = require('child_process');
const istanbul = require('istanbul');
const getInstrumentedVersion = require('./../lib/instrumentSolidity.js');
const CoverageMap = require('./../lib/coverageMap.js');

const istanbulCollector = new istanbul.Collector();
const istanbulReporter = new istanbul.Reporter();

// Very high gas block limits / contract deployment limits
const gasLimitString = '0xfffffffffff';
const gasLimitHex = 0xfffffffffff;
const gasPriceHex = 0x01;

const coverage = new CoverageMap();

// Paths
const coverageDir = './coverageEnv';        // Env that instrumented .sols are tested in

// Options
let coverageOption = '--network coverage';  // Default truffle network execution flag
let silence = '';                           // Default log level: configurable by --silence
let log = console.log;

let testrpcProcess;                         // ref to testrpc server we need to close on exit
let events;                                 // ref to string loaded from 'allFiredEvents'
let testsErrored = null;                    // flag set to non-null if truffle tests error

// --------------------------------------- Utilities -----------------------------------------------
/**
 * Removes coverage build artifacts, kills testrpc.
 * Exits (1) and prints msg on error, exits (0) otherwise.
 * @param  {String} err error message
 */
function cleanUp(err) {
  log('Cleaning up...');
  shell.config.silent = true;
  shell.rm('-Rf', `${coverageDir}`);
  shell.rm('./allFiredEvents');
  shell.rm('./scTopics');
  if (testrpcProcess) { testrpcProcess.kill(); }

  if (err) {
    log(`${err}\nExiting without generating coverage...`);
    process.exit(1);
  } else if (testsErrored) {
    log('Some truffle tests failed while running coverage');
    process.exit(1);
  } else {
    process.exit(0);
  }
}
// --------------------------------------- Script --------------------------------------------------
const config = reqCwd.silent('./.solcover.js') || {};

const workingDir = config.dir || '.';       // Relative path to contracts folder
let port = config.port || 8555;             // Port testrpc listens on
const accounts = config.accounts || 35;     // Number of accounts to testrpc launches with
const copyNodeModules = config.copyNodeModules || false; // Whether we copy node_modules when making coverage environment

// Silence shell and script logging (for solcover's unit tests / CI)
if (config.silent) {
  silence = '> /dev/null 2>&1';
  log = () => {};
}

// Generate a copy of the target project configured for solcover and save to the coverage
// environment folder.
log('Generating coverage environment');
try {
  let files = shell.ls(workingDir);
  const nmIndex = files.indexOf('node_modules');

  if (!config.copyNodeModules && nmIndex > -1) {
    files.splice(nmIndex, 1); // Removes node_modules from array.
  }

  files = files.map(file => `${workingDir}/` + file);
  shell.mkdir(coverageDir);
  shell.cp('-R', files, coverageDir);

  const truffleConfig = reqCwd.silent(`${workingDir}/truffle.js`);

  // Coverage network opts specified: use port if declared
  if (truffleConfig && truffleConfig.networks && truffleConfig.networks.coverage) {
    port = truffleConfig.networks.coverage.port || port;

  // Coverage network opts NOT specified: default to the development network w/ modified
  // port, gasLimit, gasPrice. Export the config object only.
  } else {
    const trufflejs = `
      module.exports = {
        networks: {
          development: {
            host: "localhost",
            network_id: "*",
            port: ${port},
            gas: ${gasLimitHex},
            gasPrice: ${gasPriceHex}
          }
        }
      };`;

    coverageOption = '';
    fs.writeFileSync(`${coverageDir}/truffle.js`, trufflejs);
  }
} catch (err) {
  const msg = ('There was a problem generating the coverage environment: ');
  cleanUp(msg + err);
}

// For each contract except migrations.sol:
// 1. Generate file path reference for coverage report
// 2. Load contract as string
// 3. Instrument contract
// 4. Save instrumented contract in the coverage environment folder where covered tests will run
// 5. Add instrumentation info to the coverage map
let currentFile;
try {
  shell.ls(`${coverageDir}/contracts/**/*.sol`).forEach(file => {
    const migrations = `${coverageDir}/contracts/Migrations.sol`;

    if (file !== migrations) {
      log('Instrumenting ', file);
      currentFile = file;

      const contractPath = path.resolve(file);
      const canonicalPath = contractPath.split('/coverageEnv').join('');
      const contract = fs.readFileSync(contractPath).toString();
      const instrumentedContractInfo = getInstrumentedVersion(contract, canonicalPath);
      fs.writeFileSync(contractPath, instrumentedContractInfo.contract);
      coverage.addContract(instrumentedContractInfo, canonicalPath);
    }
  });
} catch (err) {
  const msg = (`There was a problem instrumenting ${currentFile}: `);
  cleanUp(msg + err);
}

// Run modified testrpc with large block limit, on (hopefully) unused port.
// (Changes here should be also be added to the before() block of test/run.js).
if (!config.norpc) {
  const defaultRpcOptions = `--gasLimit ${gasLimitString} --accounts ${accounts} --port ${port}`;
  const testrpcOptions = config.testrpcOptions || defaultRpcOptions;
  const command = './node_modules/ethereumjs-testrpc-sc/bin/testrpc ';

  testrpcProcess = childprocess.exec(command + testrpcOptions, null, err => {
    if (err) cleanUp('testRpc errored after launching as a childprocess.');
  });
  log(`Launching testrpc on port ${port}`);
}

// Run truffle (or config.testCommand) over instrumented contracts in the
// coverage environment folder. Shell cd command needs to be invoked
// as its own statement for command line options to work, apparently.
try {
  log('Launching test command (this can take a few seconds)...');
  const defaultCommand = `truffle test ${coverageOption} ${silence}`;
  const command = config.testCommand || defaultCommand;
  shell.cd('./coverageEnv');
  shell.exec(command);
  testsErrored = shell.error();
  shell.cd('./..');
} catch (err) {
  cleanUp(err);
}

// Get events fired during instrumented contracts execution.
try {
  events = fs.readFileSync('./allFiredEvents').toString().split('\n');
  events.pop();
} catch (err) {
  const msg =
  `
    There was an error generating coverage. Possible reasons include:
    1. Another application is using port ${port}
    2. Truffle crashed because your tests errored

  `;
  cleanUp(msg + err);
}

// Generate coverage / write coverage report / run istanbul
try {
  coverage.generate(events, './contracts');

  const json = JSON.stringify(coverage.coverage);
  fs.writeFileSync('./coverage.json', json);

  istanbulCollector.add(coverage.coverage);
  istanbulReporter.add('html');
  istanbulReporter.add('lcov');
  istanbulReporter.add('text');
  istanbulReporter.write(istanbulCollector, true);
} catch (err) {
  if (config.testing) {
    cleanUp();
  } else {
    const msg = 'There was a problem generating producing the coverage map / running Istanbul.\n';
    cleanUp(msg + err);
  }
}

// Finish
cleanUp();
<|endoftext|>


<commit_before>var minimist = require('minimist');
var argv = minimist(process.argv.slice(2));
var mu = require('mu2');
var path = require('path');
var Q = require('q');
var fs = require('fs');
var crypto = require('crypto');
var spawn = require('child_process').spawn;
var dotenv = require('dotenv-save');
var pg = require('pg');
var debug = require('debug')('fire:cli');

pg.defaults.poolIdleTimeout = 500;

function mkdir(dirPath) {
	debug('Creating directory `' + dirPath + '`');

	var defer = Q.defer();
	fs.mkdir(dirPath, defer.makeNodeResolver());
	return defer.promise;
}

function space(count) {
	return new Array(count + 1).join(' ');
}

function template(source, dest, options) {
	var readStream = mu.compileAndRender(path.join(__dirname, source), options);
	var defer = Q.defer();

	debug('Compiling and rendering `' + source + '` to `' + dest + '`.');

	var writeStream = fs.createWriteStream(dest);

	var errorCallback = function(error) {
		removeEventListeners();

		defer.reject(error);
	};
	var successCallback = function() {
		removeEventListeners();

		defer.resolve(false);
	};

	var removeEventListeners = function() {
		readStream.removeListener('end', successCallback);
		writeStream.removeListener('error', errorCallback);
		writeStream.removeListener('finish', successCallback);
	};

	writeStream.once('error', errorCallback);
	readStream.once('error', errorCallback);

	writeStream.once('finish', successCallback);

	readStream.pipe(writeStream);
	return defer.promise;
}

function runCommand(command, params, cwd) {
	var defer = Q.defer();

	var options = {};
	if(cwd) {
		options.cwd = cwd;
	}
	options.stdio = 'inherit';

	var commandProcess = spawn(command, params, options);
	commandProcess.on('exit', function(code, sig) {
		if(code > 0) {
			console.log('Uh-oh. Failed to run `' + command + '`.');

			defer.reject(new Error(code));
		}
		else {
			defer.resolve(sig);
		}
	});

	return defer.promise;
}

function createApp(name) {
	if(!name) {
		console.log('Please specify an app name.');
		return;
	}

	var postfix = '';
	if(process.platform == 'win32') {
		postfix = '.cmd';
	}

	return mkdir(name)
		.then(function() {
			return mkdir(path.join(name, 'templates'));
		})
		.then(function() {
			return Q.all([
				template('skeleton/index-js.template', name + '/index.js', {name: name}),
				template('skeleton/package-json.template', name + '/package.json', {name: name}),
				template('skeleton/env.template', name + '/.env', {sessionKey: crypto.randomBytes(127).toString('base64')}),
				template('skeleton/package-json.template', name + '/package.json', {name: name}),
				template('skeleton/view-jade.template', name + '/templates/view.jade', {}),
				template('skeleton/start-jade.template', name + '/templates/start.jade', {})
			]);
		})
		.then(function() {
			return runCommand('npm' + postfix, ['install'], path.join(process.cwd(), name));
		})
		.then(function() {
			console.log(' ');
			console.log('	Created app `' + name + '`. `cd ' + name + '` and run `fire run`.');
			console.log(' ');
		});
}

function _createDatabase(datastore, name, count) {
	var defer = Q.defer();
	var databaseName = name + (count ? count : '');

	datastore.query('CREATE DATABASE ' + databaseName, function(error) {
		if(error) {
			if(error.code == '42P04') {
				_createDatabase(datastore, name, count + 1)
					.then(function(n) {
						defer.resolve(n);
					})
					.catch(function(error2) {
						defer.reject(error2);
					})
					.done();
			}
			else {
				defer.reject(error);
			}
		}
		else {
			defer.resolve(databaseName);
		}
	});
	return defer.promise;
}

function createDatastore(name) {
	if(!name) {
		var packageJson = require(path.join(process.cwd(), 'package.json'));
		name = packageJson.name;
	}

	var user = process.env.USER;
	var host = '127.0.0.1';
	var port = 5432;

	var databaseUrl = 'postgres://' + user + '@' + host + ':' + port + '/' + 'template1';

	// We have to connect to a database to create a database. So let's test if we can access the template database, see http://www.postgresql.org/docs/9.3/static/manage-ag-templatedbs.html.
	pg.connect(databaseUrl, function(error, datastore, done) {
		if(error) {
			throw new Error('Cannot connect to datastore at `' + databaseUrl + '`.');
		}
		else {
			_createDatabase(datastore, name, 0)
				.then(function(databaseName) {
					done();

					databaseUrl = 'postgres://' + user + '@' + host + ':' + port + '/' + databaseName;
					pg.connect(databaseUrl, function(error3, datastore2, done2) {
						if(error3) {
							console.log(error3);
						}
						else {
							datastore2.query('CREATE EXTENSION "uuid-ossp";', function(error4) {
								done2();

								if(error4) {
									console.log(error4);
								}
								else {
									dotenv.set('DATABASE_URL', databaseUrl);

									console.log('DATABASE_URL: ' + databaseUrl);
								}
							});
						}
					});
				})
				.catch(function(error2) {
					console.log(error2);
				})
				.done();
		}
	}.bind(this));
}

function unloadModules(basePath, index) {
	debug('unloadModules ' + basePath);

	var name = require.resolve('fire');
	if(typeof require.cache[name] != 'undefined') {
		delete require.cache[name];
	}

	name = path.join(basePath, 'node_modules', 'fire');
	if(typeof require.cache[name] != 'undefined') {
		delete require.cache[name];
	}

	var moduleName = require.resolve(path.join(basePath, index));
	if(typeof require.cache[moduleName] != 'undefined') {
		delete require.cache[moduleName];
	}

	Object.keys(require.cache).forEach(function(requireName) {
		// We destroy the cache of all files in the projects, except any libraries.
		if(requireName.indexOf(basePath) === 0 && requireName.indexOf('node_modules') == -1) {
			delete require.cache[requireName];
		}
	});
}

function loadApp(basePath, stage) {
	debug('loadApp ' + basePath + ' ' + stage);

	var packageJSON = require(path.join(basePath, 'package.json'));
	var index = packageJSON.main || 'index.js';

	unloadModules(basePath, index);

	// It's important we're retrieving the fire module used by the project. Not any global fire module.
	var firePath = path.join(basePath, 'node_modules', 'fire');

	var firestarter = require(firePath)._getFirestarter();
	firestarter.stage = stage;
	firestarter.disabled = true;
	firestarter.appsContainerMap = {};

	require(path.join(basePath, index));

	var appContainerIds = Object.keys(firestarter.appsContainerMap);
	if(appContainerIds.length > 1) {
		throw new Error('More than 1 app container found. This is currently not supported. You can create multiple apps by using the same id but different names. Please check `fire#app()`.');
	}
	else if(!appContainerIds.length) {
		throw new Error('Could not find any app. Did you create an app in ' + index + ' (this is your main entry point specified in your package.json)? Is the current working directory correct?');
	}

	var appContainer = firestarter.appsContainerMap[appContainerIds[0]];
	return appContainer.getActiveApp();
}

function getApp(stage) {
	var basePath = process.cwd();
	var app = loadApp(basePath, stage);
	var defer = Q.defer();
	setImmediate(function() {
		defer.resolve(app);
	});
	return defer.promise;
}

if(argv._.length) {
	var tasks = argv._;
	var _runTask = function(firstTask) {
		var topic, task, parameter;
		var parts = firstTask.split(':');

		if(parts.length) {
			topic = parts[0];
		}

		if(parts.length > 1) {
			task = parts[1];
		}

		if(parts.length > 2) {
			parameter = parts[2];
		}

		debug('Execute ' + topic + ':' + task + ':' + parameter);

		if(topic == 'run') {
			var _execute = function(cmd) {
		        var postfix = '';
				if(process.platform == 'win32') {
					postfix = '.cmd';
				}

		        return spawn(cmd + postfix, ['start'], {stdio: 'inherit'});
		    };

	        return _execute(path.join('node_modules', 'fire', 'node_modules', '.bin', 'nf'), ['start']);
		}
		else if(topic == 'build') {
			return getApp('build')
				.then(function(app) {
					return app.injector
						.call(function(stageMethods) {
							return stageMethods.build(task, parameter);
						})
						.finally(function() {
							return app.stop();
						});
				});
		}
		else if(topic == 'release') {
			return getApp('release')
				.then(function(app) {
					return app.injector
						.call(function(stageMethods) {
							return stageMethods.release(task, parameter);
						})
						.finally(function() {
							return app.stop();
						});
				});
		}
		else if((topic == 'app' || topic == 'apps') && (!task || task == 'create')) {
			return createApp(argv._[1] || '');
		}
		else if(topic == 'datastore' && (!task || task == 'create')) {
			return createDatastore(tasks.shift());
		}
		else if(topic == 'datastore' && task == 'open') {

		}
		else if(topic == 'config' && topic == 'get') {
			if(tasks.length) {
				var config = dotenv._load(dotenv.options({}));
				var configKey = tasks.splice(0, 1)[0];
				if(config[configKey]) {
					console.log(config[configKey].value);
				}
				else {
					console.log('');
				}
			}
			else {
				console.log('Please specify which config to get e.g. fire config:get KEY.');
			}
		}
		else if(topic == 'config' && task == 'set') {
			if(tasks.length) {
				var configMap = {};

				var index = 0;
				while(tasks.length > index) {
					var keyValue = tasks[index];
					var pair = keyValue.split('=');

					if(pair.length == 2) {
						configMap[pair[0]] = pair[1];

						dotenv.set(pair[0], pair[1]);
					}
					else {
						console.log('Please specify a key-value pair joined with a = e.g. fire config:set KEY=value');
					}

					index++;
				}
				tasks = [];

				var length = Object.keys(configMap)
					.map(function(key) {
						return key.length;
					})
					.reduce(function(last, now) {
						if(last >= now) {
							return last;
						}
						else {
							return now;
						}
					}, 0);

				Object.keys(configMap).forEach(function(key) {
					console.log(key + ': ' + space(length - key.length) + configMap[key]);
				});
			}
			else {
				console.log('Please specify which config key-value to set e.g. fire config:set KEY=value');
			}
		}
		else if(topic == 'config' && !task) {
	        var config = dotenv._load(dotenv.options({}));

			var length = Object.keys(config)
				.map(function(key) {
					return key.length;
				})
				.reduce(function(last, now) {
					if(last >= now) {
						return last;
					}
					else {
						return now;
					}
				}, 0);

			Object.keys(config).forEach(function(key) {
				console.log(key + ': ' + space(length - key.length) + config[key].value);
			});
		}
		else {
			console.log('Unknown task `' + firstTask + '`.');
		}
	};

	var _run = function() {
		var firstTask = tasks.shift();
		if(firstTask) {
			return Q.when(_runTask(firstTask))
				.then(function() {
					return _run();
				});
		}
	};

	_run()
		.then(function() {
			debug('Finished!');
		})
		.catch(function(error) {
			console.log(error);
			console.log(error.stack);
		})
		.done();
}
else {
	// show help
}
<commit_msg>adds watch topic<commit_after>var minimist = require('minimist');
var argv = minimist(process.argv.slice(2));
var mu = require('mu2');
var path = require('path');
var Q = require('q');
var fs = require('fs');
var crypto = require('crypto');
var spawn = require('child_process').spawn;
var dotenv = require('dotenv-save');
var pg = require('pg');
var debug = require('debug')('fire:cli');
var watch = require('watch');

pg.defaults.poolIdleTimeout = 500;

function mkdir(dirPath) {
	debug('Creating directory `' + dirPath + '`');

	var defer = Q.defer();
	fs.mkdir(dirPath, defer.makeNodeResolver());
	return defer.promise;
}

function space(count) {
	return new Array(count + 1).join(' ');
}

function template(source, dest, options) {
	var readStream = mu.compileAndRender(path.join(__dirname, source), options);
	var defer = Q.defer();

	debug('Compiling and rendering `' + source + '` to `' + dest + '`.');

	var writeStream = fs.createWriteStream(dest);

	var errorCallback = function(error) {
		removeEventListeners();

		defer.reject(error);
	};
	var successCallback = function() {
		removeEventListeners();

		defer.resolve(false);
	};

	var removeEventListeners = function() {
		readStream.removeListener('end', successCallback);
		writeStream.removeListener('error', errorCallback);
		writeStream.removeListener('finish', successCallback);
	};

	writeStream.once('error', errorCallback);
	readStream.once('error', errorCallback);

	writeStream.once('finish', successCallback);

	readStream.pipe(writeStream);
	return defer.promise;
}

function runCommand(command, params, cwd) {
	var defer = Q.defer();

	var options = {};
	if(cwd) {
		options.cwd = cwd;
	}
	options.stdio = 'inherit';

	var commandProcess = spawn(command, params, options);
	commandProcess.on('exit', function(code, sig) {
		if(code > 0) {
			console.log('Uh-oh. Failed to run `' + command + '`.');

			defer.reject(new Error(code));
		}
		else {
			defer.resolve(sig);
		}
	});

	return defer.promise;
}

function createApp(name) {
	if(!name) {
		console.log('Please specify an app name.');
		return;
	}

	var postfix = '';
	if(process.platform == 'win32') {
		postfix = '.cmd';
	}

	return mkdir(name)
		.then(function() {
			return mkdir(path.join(name, 'templates'));
		})
		.then(function() {
			return Q.all([
				template('skeleton/index-js.template', name + '/index.js', {name: name}),
				template('skeleton/package-json.template', name + '/package.json', {name: name}),
				template('skeleton/env.template', name + '/.env', {sessionKey: crypto.randomBytes(127).toString('base64')}),
				template('skeleton/package-json.template', name + '/package.json', {name: name}),
				template('skeleton/view-jade.template', name + '/templates/view.jade', {}),
				template('skeleton/start-jade.template', name + '/templates/start.jade', {})
			]);
		})
		.then(function() {
			return runCommand('npm' + postfix, ['install'], path.join(process.cwd(), name));
		})
		.then(function() {
			console.log(' ');
			console.log('	Created app `' + name + '`. `cd ' + name + '` and run `fire run`.');
			console.log(' ');
		});
}

function _createDatabase(datastore, name, count) {
	var defer = Q.defer();
	var databaseName = name + (count ? count : '');

	datastore.query('CREATE DATABASE ' + databaseName, function(error) {
		if(error) {
			if(error.code == '42P04') {
				_createDatabase(datastore, name, count + 1)
					.then(function(n) {
						defer.resolve(n);
					})
					.catch(function(error2) {
						defer.reject(error2);
					})
					.done();
			}
			else {
				defer.reject(error);
			}
		}
		else {
			defer.resolve(databaseName);
		}
	});
	return defer.promise;
}

function createDatastore(name) {
	if(!name) {
		var packageJson = require(path.join(process.cwd(), 'package.json'));
		name = packageJson.name;
	}

	var user = process.env.USER;
	var host = '127.0.0.1';
	var port = 5432;

	var databaseUrl = 'postgres://' + user + '@' + host + ':' + port + '/' + 'template1';

	// We have to connect to a database to create a database. So let's test if we can access the template database, see http://www.postgresql.org/docs/9.3/static/manage-ag-templatedbs.html.
	pg.connect(databaseUrl, function(error, datastore, done) {
		if(error) {
			throw new Error('Cannot connect to datastore at `' + databaseUrl + '`.');
		}
		else {
			_createDatabase(datastore, name, 0)
				.then(function(databaseName) {
					done();

					databaseUrl = 'postgres://' + user + '@' + host + ':' + port + '/' + databaseName;
					pg.connect(databaseUrl, function(error3, datastore2, done2) {
						if(error3) {
							console.log(error3);
						}
						else {
							datastore2.query('CREATE EXTENSION "uuid-ossp";', function(error4) {
								done2();

								if(error4) {
									console.log(error4);
								}
								else {
									dotenv.set('DATABASE_URL', databaseUrl);

									console.log('DATABASE_URL: ' + databaseUrl);
								}
							});
						}
					});
				})
				.catch(function(error2) {
					console.log(error2);
				})
				.done();
		}
	}.bind(this));
}

function unloadModules(basePath, index) {
	debug('unloadModules ' + basePath);

	var name = require.resolve('fire');
	if(typeof require.cache[name] != 'undefined') {
		delete require.cache[name];
	}

	name = path.join(basePath, 'node_modules', 'fire');
	if(typeof require.cache[name] != 'undefined') {
		delete require.cache[name];
	}

	var moduleName = require.resolve(path.join(basePath, index));
	if(typeof require.cache[moduleName] != 'undefined') {
		delete require.cache[moduleName];
	}

	Object.keys(require.cache).forEach(function(requireName) {
		// We destroy the cache of all files in the projects, except any libraries.
		if(requireName.indexOf(basePath) === 0 && requireName.indexOf('node_modules') == -1) {
			delete require.cache[requireName];
		}
	});
}

function loadApp(basePath, stage) {
	debug('loadApp ' + basePath + ' ' + stage);

	var packageJSON = require(path.join(basePath, 'package.json'));
	var index = packageJSON.main || 'index.js';

	unloadModules(basePath, index);

	// It's important we're retrieving the fire module used by the project. Not any global fire module.
	var firePath = path.join(basePath, 'node_modules', 'fire');

	var firestarter = require(firePath)._getFirestarter();
	firestarter.stage = stage;
	firestarter.disabled = true;
	firestarter.appsContainerMap = {};

	require(path.join(basePath, index));

	var appContainerIds = Object.keys(firestarter.appsContainerMap);
	if(appContainerIds.length > 1) {
		throw new Error('More than 1 app container found. This is currently not supported. You can create multiple apps by using the same id but different names. Please check `fire#app()`.');
	}
	else if(!appContainerIds.length) {
		throw new Error('Could not find any app. Did you create an app in ' + index + ' (this is your main entry point specified in your package.json)? Is the current working directory correct?');
	}

	var appContainer = firestarter.appsContainerMap[appContainerIds[0]];
	return appContainer.getActiveApp();
}

function getApp(stage) {
	var basePath = process.cwd();
	var app = loadApp(basePath, stage);
	var defer = Q.defer();
	setImmediate(function() {
		defer.resolve(app);
	});
	return defer.promise;
}

function CLI(tasks) {
	var _doRun = function() {
		var _execute = function(cmd) {
			var postfix = '';
			if(process.platform == 'win32') {
				postfix = '.cmd';
			}

			return spawn(cmd + postfix, ['start'], {stdio: 'inherit'});
		};

		return _execute(path.join('node_modules', 'fire', 'node_modules', '.bin', 'nf'), ['start']);
	};

	var _doBuild = function(action, parameter) {
		return getApp('build')
			.then(function(app) {
				return app.injector
					.call(function(stageMethods) {
						return stageMethods.build(action, parameter);
					})
					.finally(function() {
						return app.stop();
					});
			});
	};

	var _doRelease = function(action, parameter) {
		return getApp('release')
			.then(function(app) {
				return app.injector
					.call(function(stageMethods) {
						return stageMethods.release(action, parameter);
					})
					.finally(function() {
						return app.stop();
					});
			});
	};

	var _doApp = function() {
		return createApp(tasks.shift() || '');
	};

	var _doDatastore = function(action) {
		if(action == 'create' || !action) {
			return createDatastore(tasks.shift());
		}
		else if(action == 'open') {
			var config = dotenv._load(dotenv.options({}));
			return runCommand('psql', [config.DATABASE_URL.value]);
		}
	};

	var _doServe = function() {
		var runProcess = null;
		var isBuilding = false;

		var _run = function() {
			var _execute = function(cmd) {
				var postfix = '';
				if(process.platform == 'win32') {
					postfix = '.cmd';
				}

				return spawn(cmd + postfix, ['start'], {stdio: 'inherit'});
			};

			if(runProcess) {
				debug('Killing existing run process.');

				runProcess.once('close', function() {
					runProcess = null;
					_run();
				});

				// We're using (node-)foreman to run our app which explicitly listens to SIGINT to kill all of it's child processes.
				runProcess.kill('SIGINT');
			}
			else {
				runProcess = _execute(path.join('node_modules', 'fire', 'node_modules', '.bin', 'nf'), ['start']);
			}
		};

		debug('Watching for changes on: ' + process.cwd());

		watch.createMonitor(process.cwd(), {ignoreDirectoryPattern: new RegExp('/.fire/')}, function(monitor) {
			var _filesChanged = function(file) {
				// Now, build everything. After the build, decide if we want to re-start.
				console.log('A file changed. Building.');
				console.log(file);
				console.log('Is building: ' + isBuilding);

				isBuilding = true;

				_doBuild()
					.then(function() {
						isBuilding = false;
						return _run();
					})
					.done();
			};
			monitor.on('created', _filesChanged);
			monitor.on('changed', _filesChanged);
			monitor.on('removed', _filesChanged);
		});
		_run();
	};

	var _doConfig = function(action) {
		var config = {};
		if(action == 'get') {
			if(tasks.length) {
				config = dotenv._load(dotenv.options({}));
				var configKey = tasks.splice(0, 1)[0];
				if(config[configKey]) {
					console.log(config[configKey].value);
				}
				else {
					console.log('');
				}
			}
			else {
				console.log('Please specify which config to get e.g. fire config:get KEY.');
			}
		}
		else if(action == 'set') {
			if(tasks.length) {
				var newConfig = {};
				var index = 0;
				while(tasks.length > index) {
					var keyValue = tasks[index];
					var pair = keyValue.split('=');

					if(pair.length == 2) {
						newConfig[pair[0]] = pair[1];

						dotenv.set(pair[0], pair[1]);
					}
					else {
						console.log('Please specify a key-value pair joined with a = e.g. fire config:set KEY=value');
					}

					index++;
				}
				tasks = [];

				var newConfigLength = Object.keys(newConfig)
					.map(function(key) {
						return key.length;
					})
					.reduce(function(last, now) {
						if(last >= now) {
							return last;
						}
						else {
							return now;
						}
					}, 0);

				Object.keys(newConfig).forEach(function(key) {
					console.log(key + ': ' + space(newConfigLength - key.length) + newConfig[key]);
				});
			}
			else {
				console.log('Please specify which config key-value to set e.g. fire config:set KEY=value');
			}
		}
		else if(!action) {
	        config = dotenv._load(dotenv.options({}));

			var length = Object.keys(config)
				.map(function(key) {
					return key.length;
				})
				.reduce(function(last, now) {
					if(last >= now) {
						return last;
					}
					else {
						return now;
					}
				}, 0);

			Object.keys(config).forEach(function(key) {
				console.log(key + ': ' + space(length - key.length) + config[key].value);
			});
		}
	};

	var _showHelp = function() {
		var _show = function(message) {
			return message + space(32 - message.length);
		};

		console.log([
			'Usage: fire TOPIC[:ACTION[:PARAMETER]] ...',
			'',
			'List of topics and actions:',
			''
		].join('\n'));

		var meta = {
			'build': 'builds migrations, templates, and all other static assets',
			'build:version': 'sets the Node on Fire version in .fire/VERSION',
			'build:procfile': 'generates the Procfile with all processes',
			'build:templates': 'compiles all Jade templates in templates/',
			'build:less': 'compiles styles/default.less',
			'build:migrations': 'generates migrations based on model changes',
			'build:browserify': 'generates one bundle.js from all scripts',
			'build:scripts': 'generates all client-side javascript',
			'build:uglify': 'uglifies the bundle.js',
			'build:api': 'generates rest http api',

			'release': 'applies datastore migrations and creates A/B tests',
			'release:tests': 'prepares A/B tests',
			'release:migrate': 'applies all datastore migrations',
			'release:migrate:VERSION': 'applies datastore migrations, either up or down, till VERSION',

			'run': 'starts all processes of your app',

			'serve': 'runs your app, builds on changes to files and restarts',

			'config': 'shows all local config key-value pairs (stored in .env)',
			'config:get KEY': 'shows the local config value of KEY',
			'config:set KEY=VALUE ...': 'sets the local config KEY to VALUE',

			'apps:create APP': 'creates a new app named APP',

			'datastore:create': 'creates a new local database, installs the uuid-ossp extension and sets the DATABASE_URL locally',
			'datastore:open': 'opens the current local database configured in DATABASE_URL',

			'help': 'shows this help'
		};

		console.log(Object.keys(meta).sort().map(function(key) {
			return [space(2), _show(key), '# ', meta[key]].join('');
		}).join('\n'));
		console.log('');
	};

	var _runTask = function(task) {
		var topic, action, parameter;
		var parts = task.split(':');

		if(parts.length) {
			topic = parts[0];
		}

		if(parts.length > 1) {
			action = parts[1];
		}

		if(parts.length > 2) {
			parameter = parts[2];
		}

		debug('Execute ' + topic + ':' + action + ':' + parameter);

		if(topic == 'run') {
			return _doRun(action, parameter);
		}
		else if(topic == 'build') {
			return _doBuild(action, parameter);
		}
		else if(topic == 'release') {
			return _doRelease(action, parameter);
		}
		else if((topic == 'app' || topic == 'apps')) {
			return _doApp(action, parameter);
		}
		else if(topic == 'datastore' || topic == 'pg') {
			return _doDatastore(action, parameter);
		}
		else if(topic == 'serve') {
			return _doServe();
		}
		else if(topic == 'config') {
			return _doConfig(action, parameter);
		}
		else if(topic == 'help') {
			return _showHelp();
		}
		else {
			console.log('Unknown topic `' + topic + '`.');
		}
	};

	var _run = function() {
		var task = tasks.shift();
		if(task) {
			return Q.when(_runTask(task))
				.then(function() {
					return _run();
				});
		}
	};

	if(tasks.length) {
		_run();
	}
	else {
		_showHelp();
	}
}

new CLI(argv._);
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

/* Gear task runner. Executes Gearfile using a tasks workflow.
 * See http://gearjs.org/#tasks.tasks
 *
 * Usage:
 * > gear [options]
 *
 * Available options:
 * --cwd <dir>        change working directory
 * --Gearfile <path>  execute a specific gearfile
 */
var Liftoff = require('liftoff'),
    vm = require('vm'),
    path = require('path'),
    fs = require('fs'),
    filename = 'Gearfile',
    existsSync = fs.existsSync || path.existsSync; // 0.6 compat

var GearCLI = new Liftoff({
    name: 'Gear',
    configName: filename,
    extensions: {
        '': null,
        '.js': null
    }
});

GearCLI.launch(function(env) {
    // Loads a local install of gear. Falls back to the global install.
    var gear = require(env.modulePath || '../index');
    if(process.cwd !== env.configBase) {
        process.chdir(env.configBase);
    }

    if (!env.configPath) {
        notify(filename + ' not found');
        process.exit(1);
    }

    var tasks;
    try {
        tasks = vm.runInNewContext('var tasks = ' + fs.readFileSync(env.configPath) + '; tasks;', {
            require: require,
            process: process,
            console: console,
            gear: gear
        }, env.configPath, true);
    } catch(e) {
        notify(e);
        process.exit(1);
    }

    if (tasks) {
        new gear.Queue({registry: new gear.Registry({module: 'gear-lib'})})
            .tasks(tasks)
            .run(function(err, res) {
                if (err) {
                    notify(err);
                }
            });
    }
});

function notify(msg) {
    console.error('gear: ', msg);
}
<commit_msg>Fix minor cwd bug<commit_after>#!/usr/bin/env node
'use strict';

/* Gear task runner. Executes Gearfile using a tasks workflow.
 * See http://gearjs.org/#tasks.tasks
 *
 * Usage:
 * > gear [options]
 *
 * Available options:
 * --cwd <dir>        change working directory
 * --Gearfile <path>  execute a specific gearfile
 */
var Liftoff = require('liftoff'),
    vm = require('vm'),
    path = require('path'),
    fs = require('fs'),
    filename = 'Gearfile',
    existsSync = fs.existsSync || path.existsSync; // 0.6 compat

var GearCLI = new Liftoff({
    name: 'Gear',
    configName: filename,
    extensions: {
        '': null,
        '.js': null
    }
});

GearCLI.launch(function(env) {
    // Loads a local install of gear. Falls back to the global install.
    var gear = require(env.modulePath || '../index');
    if(process.cwd() !== env.configBase) {
        process.chdir(env.configBase);
    }

    if (!env.configPath) {
        notify(filename + ' not found');
        process.exit(1);
    }

    var tasks;
    try {
        tasks = vm.runInNewContext('var tasks = ' + fs.readFileSync(env.configPath) + '; tasks;', {
            require: require,
            process: process,
            console: console,
            gear: gear
        }, env.configPath, true);
    } catch(e) {
        notify(e);
        process.exit(1);
    }

    if (tasks) {
        new gear.Queue({registry: new gear.Registry({module: 'gear-lib'})})
            .tasks(tasks)
            .run(function(err, res) {
                if (err) {
                    notify(err);
                }
            });
    }
});

function notify(msg) {
    console.error('gear: ', msg);
}
<|endoftext|>


<commit_before>var express = require('express');
var http = require('http');

var handler = require('../servers/' + process.argv[2] + '/handler.js');
var port = process.argv[3];

var general_test = process.argv[4] === 't';
var micro_test = process.argv[4] === 'mt';

//CREATE EXPRESS APP
var app = express();
var httpServer;
handler(app,function(err){

	if (err){
		console.error(err);
		process.exit(1);
	}

	httpServer = http.createServer(app).listen(port,'localhost',function(){
		console.log("Server running at port %s",httpServer.address().port)
	});
},general_test || micro_test);

process.on('SIGINT',function(){
	httpServer.close(function(){
		process.exit(0);
	});
})

if (micro_test) {
	process.send = console.log
}
<commit_msg>stupid http<commit_after>var express = require('express');
var http = require('http');

var handler = require('../servers/' + process.argv[2] + '/handler.js');
var port = process.argv[3];

var general_test = process.argv[4] === 't';
var micro_test = process.argv[4] === 'mt';

//CREATE EXPRESS APP
var app = express();
var httpServer = http.createServer(app);
handler(app,httpServer,function(err){

	if (err){
		console.error(err);
		process.exit(1);
	}

	httpServer.listen(port,'localhost',function(){
		console.log("Server running at port %s",httpServer.address().port)
	});
},general_test || micro_test);

process.on('SIGINT',function(){
	httpServer.close(function(){
		process.exit(0);
	});
})

if (micro_test) {
	process.send = console.log
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

/**
 * This file is meant to be linked as a "kbox" executable.
 */

var fs = require('fs');
var path = require('path');

var _ = require('lodash');
var argv = require('minimist')(process.argv.slice(2));
var chalk = require('chalk');
var Liftoff = require('liftoff');
var tildify = require('tildify');

var kconfig = require('../lib/config.js');
//var app = require('../lib/app.js');
var manager = require('../lib/manager.js');

// set env var for ORIGINAL cwd
// before anything touches it
process.env.INIT_CWD = process.cwd();

var cli = new Liftoff({
  name: 'profile',
  configName: '.kalabox',
  extensions: {
    '.json': null
  },
  modulePath: path.resolve(__dirname, '../'),
  modulePackage: path.resolve(__dirname, '../package.json')
});

// exit with 0 or 1
var failed = false;
process.once('exit', function(code) {
  if (code === 0 && failed) {
    process.exit(1);
  }
});

var cliPackage = require('../package');
var versionFlag = argv.v || argv.version;
var tasksFlag = argv.T || argv.tasks;
var tasks = argv._;
var toRun = tasks.length ? tasks : ['default'];

cli.on('require', function (name) {
  console.log('Requiring external module', chalk.magenta(name));
});

cli.on('requireFail', function (name) {
  console.log(chalk.red('Failed to load external module'), chalk.magenta(name));
});

cli.launch({
  cwd: argv.cwd,
  configPath: argv.kalaboxfile,
  require: argv.require,
  completion: argv.completion,
  verbose: argv.verbose,
  app: argv.app
}, handleArguments);

function handleArguments(env) {
  if (argv.verbose) {
    console.log(chalk.yellow('LIFTOFF SETTINGS:'), this);
    console.log(chalk.yellow('CLI OPTIONS:'), argv);
    console.log(chalk.yellow('CWD:'), env.cwd);
    console.log(chalk.red('APP CONFIG LOCATION:'),  env.configPath);
    console.log(chalk.red('APP CONFIG BASE DIR:'), env.configBase);
    console.log(chalk.cyan('KALABOX MODULE LOCATION:'), this.modulePath);
    console.log(chalk.cyan('KALABOX PACKAGE.JSON LOCATION:'), this.modulePackage);
    console.log(chalk.cyan('KALABOX PACKAGE.JSON'), require('../package'));
  }

  var workingDir = env.cwd;
  var configPath = path.join(env.cwd, '.kalabox', 'profile.json');

  if (argv.app) {
    var apppath = path.resolve(kconfig.appDataPath, argv.app);
    if (!fs.existsSync(apppath) || !fs.existsSync(path.resolve(apppath, 'app.json'))) {
      console.log(chalk.red('App config not found.'));
      process.exit(1);
    }

    // Load up the app data from ~/.kalabox/apps/<app>/app.json
    var appdata = require(path.resolve(apppath, 'app.json'));
    console.log(appdata.path);
    workingDir = appdata.path;
    configPath = path.resolve(appdata.profilePath, 'profile.json');
  }

  if (configPath) {
    process.chdir(workingDir);
    env.app = new manager.App(manager, workingDir);
  }

  env.manager = manager;

  if (argv.verbose) {
    console.log(chalk.red('APP CONFIG:'), env.config);
    console.log('Using config file', chalk.magenta(tildify(env.configPath)));
  }

  processTask(env);
}

function processTask(env) {
  var cmd = argv._[0];
  // Run command against app if it exists
  if (env.app && env.app.manager.tasks[cmd]) {
    env.manager.tasks[cmd]();
  }
  // If not, run as a manager task if it exists
  else if (env.manager.tasks[cmd]) {
    env.manager.tasks[cmd]();
  }
  else {
    console.log(chalk.red('Command'), chalk.cyan(cmd), chalk.red('not found.'));
  }
}<commit_msg>fixed global tasks so they can be executed outside the context of an app directory. i.e. kbox list<commit_after>#!/usr/bin/env node

'use strict';

/**
 * This file is meant to be linked as a "kbox" executable.
 */

var fs = require('fs');
var path = require('path');

var _ = require('lodash');
var argv = require('minimist')(process.argv.slice(2));
var chalk = require('chalk');
var Liftoff = require('liftoff');
var tildify = require('tildify');

var kconfig = require('../lib/config.js');
var manager = require('../lib/manager.js');
var App = require('../lib/app.js');

// set env var for ORIGINAL cwd
// before anything touches it
process.env.INIT_CWD = process.cwd();

var cli = new Liftoff({
  name: 'profile',
  configName: '.kalabox',
  extensions: {
    '.json': null
  },
  modulePath: path.resolve(__dirname, '../'),
  modulePackage: path.resolve(__dirname, '../package.json')
});

// exit with 0 or 1
var failed = false;
process.once('exit', function(code) {
  if (code === 0 && failed) {
    process.exit(1);
  }
});

var cliPackage = require('../package');
var versionFlag = argv.v || argv.version;
var tasksFlag = argv.T || argv.tasks;
var tasks = argv._;
var toRun = tasks.length ? tasks : ['default'];

cli.on('require', function (name) {
  console.log('Requiring external module', chalk.magenta(name));
});

cli.on('requireFail', function (name) {
  console.log(chalk.red('Failed to load external module'), chalk.magenta(name));
});

cli.launch({
  cwd: argv.cwd,
  configPath: argv.kalaboxfile,
  require: argv.require,
  completion: argv.completion,
  verbose: argv.verbose,
  app: argv.app
}, handleArguments);

function handleArguments(env) {
  if (argv.verbose) {
    console.log(chalk.yellow('LIFTOFF SETTINGS:'), this);
    console.log(chalk.yellow('CLI OPTIONS:'), argv);
    console.log(chalk.yellow('CWD:'), env.cwd);
    console.log(chalk.red('APP CONFIG LOCATION:'),  env.configPath);
    console.log(chalk.red('APP CONFIG BASE DIR:'), env.configBase);
    console.log(chalk.cyan('KALABOX MODULE LOCATION:'), this.modulePath);
    console.log(chalk.cyan('KALABOX PACKAGE.JSON LOCATION:'), this.modulePackage);
    console.log(chalk.cyan('KALABOX PACKAGE.JSON'), require('../package'));
  }

  var workingDir = env.cwd;
  var configPath = path.join(env.cwd, '.kalabox', 'profile.json');

  if (argv.app) {
    var apppath = path.resolve(kconfig.appDataPath, argv.app);
    if (!fs.existsSync(apppath) || !fs.existsSync(path.resolve(apppath, 'app.json'))) {
      console.log(chalk.red('App config not found.'));
      process.exit(1);
    }

    // Load up the app data from ~/.kalabox/apps/<app>/app.json
    var appdata = require(path.resolve(apppath, 'app.json'));
    workingDir = appdata.path;
    configPath = path.resolve(appdata.profilePath, 'profile.json');
  }

  if (fs.existsSync(configPath)) {
    process.chdir(workingDir);
    env.app = new App(manager, workingDir);
  }

  env.manager = manager;

  if (argv.verbose) {
    console.log(chalk.red('APP CONFIG:'), env.config);
    console.log('Using config file', chalk.magenta(tildify(env.configPath)));
  }

  processTask(env);
}

function processTask(env) {
  var cmd = argv._[0];
  // Run command against app if it exists
  if (env.app && env.app.manager.tasks[cmd]) {
    env.app.manager.tasks[cmd]();
  }

  // If not, run as a manager task if it exists
  else if (env.manager.tasks[cmd]) {
    env.manager.tasks[cmd]();
  }
  else {
    console.log(chalk.red('Command'), chalk.cyan(cmd), chalk.red('not found.'));
  }
}
<|endoftext|>


<commit_before>let commander = require('commander')
let winston = require('winston')
let install = require('../lib/install')
let util = require('../lib/util')

winston.setLevels(winston.config.cli.levels)
winston.cli()

let verbosityLevels = [ 'info', 'debug', 'verbose', 'silly' ]
let increaseVerbosity = function (v, total) {
  winston.level = verbosityLevels[total]
  return total + (total < verbosityLevels.length - 1)
}

commander
  .version(require('../package.json').version)
  .option('-v, --verbose', 'increase verbosity', increaseVerbosity, 0)

commander
  .command('install <packages...>')
  .alias('i')
  .description('install one or more packages')
  .action(packages => {
    let startProfile = util.getCurrentProfile()
    winston.info(`Current Minecraft version: ${startProfile.version}`)
    winston.info(`Current profile name: ${startProfile.originalInfo.name}`)
    console.log()

    packages.forEach(pkg => {
      let result = install(pkg)
      if (result instanceof Error) {
        winston.error(`${pkg}: ${result.name}: ${result.message}`)
      }
    })

    let endProfile = util.getCurrentProfile()
    if ((endProfile.version !== startProfile.version) ||
      (endProfile.originalInfo.name !== startProfile.originalInfo.name)) {
      console.log()
      winston.info(`Current Minecraft version: ${endProfile.version}`)
      return winston.info(`Current profile name: ${endProfile.originalInfo.name}`)
    }
  })

commander
  .command('minecraft-version')
  .alias('mc')
  .description('display currently selected Minecraft version')
  .action(function () {
    util.getClientVersion(version => console.log(version))
  })

commander.on('--help', () => console.log([
  '  Examples:',
  '',
  '    Install a package from the ./foo directory',
  '      $ mcpm install ./foo',
  '',
  '    Install a package from the ./foo.zip archive',
  '      $ mcpm install ./foo.zip',
  '',
  '    Install a package from cache',
  '      $ mcpm install foo@0.2.0',
  '',
  '    Show the Minecraft version of the currently selected profile',
  '      $ mcpm mc'
].join('\n')
)

)

commander
  .parse(process.argv)
<commit_msg>fix(bin/mcpm): add shebang to make CLI work on Windows<commit_after>#!/usr/bin/env node

let commander = require('commander')
let winston = require('winston')
let install = require('../lib/install')
let util = require('../lib/util')

winston.setLevels(winston.config.cli.levels)
winston.cli()

let verbosityLevels = [ 'info', 'debug', 'verbose', 'silly' ]
let increaseVerbosity = function (v, total) {
  winston.level = verbosityLevels[total]
  return total + (total < verbosityLevels.length - 1)
}

commander
  .version(require('../package.json').version)
  .option('-v, --verbose', 'increase verbosity', increaseVerbosity, 0)

commander
  .command('install <packages...>')
  .alias('i')
  .description('install one or more packages')
  .action(packages => {
    let startProfile = util.getCurrentProfile()
    winston.info(`Current Minecraft version: ${startProfile.version}`)
    winston.info(`Current profile name: ${startProfile.originalInfo.name}`)
    console.log()

    packages.forEach(pkg => {
      let result = install(pkg)
      if (result instanceof Error) {
        winston.error(`${pkg}: ${result.name}: ${result.message}`)
      }
    })

    let endProfile = util.getCurrentProfile()
    if ((endProfile.version !== startProfile.version) ||
      (endProfile.originalInfo.name !== startProfile.originalInfo.name)) {
      console.log()
      winston.info(`Current Minecraft version: ${endProfile.version}`)
      return winston.info(`Current profile name: ${endProfile.originalInfo.name}`)
    }
  })

commander
  .command('minecraft-version')
  .alias('mc')
  .description('display currently selected Minecraft version')
  .action(function () {
    util.getClientVersion(version => console.log(version))
  })

commander.on('--help', () => console.log([
  '  Examples:',
  '',
  '    Install a package from the ./foo directory',
  '      $ mcpm install ./foo',
  '',
  '    Install a package from the ./foo.zip archive',
  '      $ mcpm install ./foo.zip',
  '',
  '    Install a package from cache',
  '      $ mcpm install foo@0.2.0',
  '',
  '    Show the Minecraft version of the currently selected profile',
  '      $ mcpm mc'
].join('\n')
)

)

commander
  .parse(process.argv)
<|endoftext|>


<commit_before>#!/usr/bin/env node

const boot = async() => {
    const path = require('path')
    const { ensurePreferencesFilename, getPreferencesDirectory } = require('@pown/preferences')

    // stage0: add the local node_modules to the module search path

    module.paths.push(path.join(__dirname, '..', 'node_modules'))

    // stage1: setup pown root

    if (!process.env.POWN_ROOT) {
        process.env.POWN_ROOT = path.join(__dirname, '..')
    }

    // stage2: add modules node_modules to the module search path

    await ensurePreferencesFilename('modules', 'package.json')

    const dirname = getPreferencesDirectory('modules')

    module.paths.push(dirname)

    // stage3: setup pown modules

    process.env.POWN_PATH = [...(process.env.POWN_PATH ? process.env.POWN_PATH : []), dirname].join(path.delimiter)

    // stage4: launch

    require('@pown/cli/bin/cli')
}

boot()
<commit_msg>Code-quality improvements.<commit_after>#!/usr/bin/env node

const boot = async() => {
    const path = require('path')
    const { ensurePreferencesFilename, getPreferencesDirectory } = require('@pown/preferences')

    // stage0: add the local node_modules to the module search path

    module.paths.push(path.join(__dirname, '..', 'node_modules'))

    // stage1: setup pown root

    if (!process.env.POWN_ROOT) {
        process.env.POWN_ROOT = path.join(__dirname, '..')
    }

    // stage2: add modules node_modules to the module search path

    await ensurePreferencesFilename('modules', 'package.json')

    const dirname = getPreferencesDirectory('modules')

    module.paths.push(dirname)

    // stage3: setup pown modules

    process.env.POWN_PATH = [...(process.env.POWN_PATH ? [process.env.POWN_PATH] : []), dirname].join(path.delimiter)

    // stage4: launch

    require('@pown/cli/bin/cli')
}

boot()
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 *Instalation:
 * ~ cd <yoson-repo>
 * ~ ln -s ../../validate-commit-message.js .git/hooks/commit-msg
 */

'use strict';

var fs = require('fs');
var util = require('util');

var MAX_LENGTH = 100;
var PATTERN = /^(?:fixup!\s*)?(\w*)(\(([w\$\.\*/-]*)\))?\: (.*)$/;
var IGNORED = /^WIP\:/;
var TYPES ={
    feat: true,
    fix: true,
    docs: true,
    style: true,
    refactor: true,
    perf: true,
    test: true,
    chore: true,
    revert: true
};

var MSG = {
    IGNORED: "Commit message validation ignored.",
    ERROR:{
        MAX_LENGTH: 'Is longer than %d characters !',
        PATTERN: 'Does not match "<type>(<scope>): <subject>" ! was:',
        TYPES: '"%s" is not allowed type !'
    }
};

var log = console.log;
var logError = function(){
    console.error('INVALID COMMIT MSG:' + util.format.apply(null, arguments));
};

var isMessageIgnored = function(message){
    return IGNORED.test(message);
};

var validateMessage = function(message){
    var isValid = true;
    if(isMessageIgnored(message)){
        log(MSG.IGNORED);
        return true;
    }

    if(message.length > MAX_LENGTH){
        logError(, MAX_LENGTH);
    }

    var match = PATTERN.exec(message);

    if(!match){
        logError(MSG.ERROR.PATTERN + message);
        return false;
    }

    var type = match[1];
    var scope = match[3];
    var subject = match[4];

    if(!TYPES.hasOwnProperty(type)){
        logError(MSG.ERROR.TYPES, type);
        return false;
    }
    // Some more ideas, do want anything like this ?
    // - allow only specific scopes (eg. fix(docs) should not be allowed ?
    // - auto correct the type to lower case ?
    // - auto correct first letter of the subject to lower case ?
    // - auto add empty line after subject ?
    // - auto remove empty () ?
    // - auto correct typos in type ?
    // - store incorrect messages, so that we can learn
    return isValid;
};

var firstLineFromBuffer = function(buffer){
    return buffer.toString().split('\n').shift();
};

//publish for testing
exports.validateMessage = validateMessage;

//hack start if not run by jasmine :-D
if(process.argv.join('').indexOf('jasmine-node') === -1){
    var commitMsgFile = process.argv[2];
    var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs');

    fs.readFile(commitMsgFile, function(err, buffer){
        var msg = firstLineFromBuffer(buffer);

        if(!validateMessage(msg)){
            fs.appendFile(incorrectLogFile, msg + '\n', function(){
                process.exit(0);
            });
        } else {
            process.exit(0);
        }
    });
}
<commit_msg>chore(commit) Append the validation of commit<commit_after>#!/usr/bin/env node
/**
 * Script to validate the format of commit
 * Instalation:
 * ~ cd <yoson-repo>
 * ~ ln -s ../../validate-commit-message.js .git/hooks/commit-msg
 */

'use strict';

var fs = require('fs');
var util = require('util');

var MAX_LENGTH = 100;
var PATTERN = /^(?:fixup!\s*)?(\w*)(\(([w\$\.\*/-]*)\))?\: (.*)$/;
var IGNORED = /^WIP\:/;
var TYPES ={
    feat: true,
    fix: true,
    docs: true,
    style: true,
    refactor: true,
    perf: true,
    test: true,
    chore: true,
    revert: true
};

var MSG = {
    IGNORED: "Commit message validation ignored.",
    ERROR:{
        MAX_LENGTH: 'Is longer than %d characters !',
        PATTERN: 'Does not match "<type>(<scope>): <subject>" ! was:',
        TYPES: '"%s" is not allowed type !'
    }
};

var log = console.log;
var logError = function(){
    console.error('INVALID COMMIT MSG:' + util.format.apply(null, arguments));
};

var isMessageIgnored = function(message){
    return IGNORED.test(message);
};

var validateMessage = function(message){
    var isValid = true;
    if(isMessageIgnored(message)){
        log(MSG.IGNORED);
        return true;
    }

    if(message.length > MAX_LENGTH){
        logError(, MAX_LENGTH);
    }

    var match = PATTERN.exec(message);

    if(!match){
        logError(MSG.ERROR.PATTERN + message);
        return false;
    }

    var type = match[1];
    var scope = match[3];
    var subject = match[4];

    if(!TYPES.hasOwnProperty(type)){
        logError(MSG.ERROR.TYPES, type);
        return false;
    }
    // Some more ideas, do want anything like this ?
    // - allow only specific scopes (eg. fix(docs) should not be allowed ?
    // - auto correct the type to lower case ?
    // - auto correct first letter of the subject to lower case ?
    // - auto add empty line after subject ?
    // - auto remove empty () ?
    // - auto correct typos in type ?
    // - store incorrect messages, so that we can learn
    return isValid;
};

var firstLineFromBuffer = function(buffer){
    return buffer.toString().split('\n').shift();
};

//publish for testing
exports.validateMessage = validateMessage;

//hack start if not run by jasmine :-D
if(process.argv.join('').indexOf('jasmine-node') === -1){
    var commitMsgFile = process.argv[2];
    var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs');

    fs.readFile(commitMsgFile, function(err, buffer){
        var msg = firstLineFromBuffer(buffer);

        if(!validateMessage(msg)){
            fs.appendFile(incorrectLogFile, msg + '\n', function(){
                process.exit(0);
            });
        } else {
            process.exit(0);
        }
    });
}
<|endoftext|>


<commit_before>#! /usr/bin/env node
process.argv.push('--colors');

require('jest/bin/jest');
<commit_msg>Set NODE_ENV to test before testing.<commit_after>#! /usr/bin/env node
process.env.NODE_ENV = 'test';
process.argv.push('--colors');

require('jest/bin/jest');
<|endoftext|>


<commit_before>const utils = require('../../utils')
const tsv = require('./tsv')

const validate = (
  files,
  fileList,
  tsvs,
  events,
  participants,
  phenotypeParticipants,
  stimuli,
) => {
  let issues = []
  // validate tsv
  const tsvPromises = files.map(function(file) {
    return new Promise(resolve => {
      utils.files.readFile(file).then(contents => {
        // Push TSV to list for custom column verification after all data dictionaries have been read
        tsvs.push({
          file: file,
          contents: contents,
        })
        if (file.name.endsWith('_events.tsv')) {
          events.push({
            file: file,
            path: file.relativePath,
            contents: contents,
          })
        }
        tsv(file, contents, fileList, function(
          tsvIssues,
          participantList,
          stimFiles,
        ) {
          if (participantList) {
            if (file.name.endsWith('participants.tsv')) {
              participants = {
                list: participantList,
                file: file,
              }
            } else if (file.relativePath.includes('phenotype/')) {
              phenotypeParticipants.push({
                list: participantList,
                file: file,
              })
            }
          }
          if (stimFiles && stimFiles.length) {
            // add unique new events to the stimuli.events array
            stimuli.events = [...new Set([...stimuli.events, ...stimFiles])]
          }
          issues = issues.concat(tsvIssues)
          return resolve()
        })
      })
    })
  })

  return new Promise(resolve =>
    Promise.all(tsvPromises).then(() => resolve(issues)),
  )
}

module.exports = validate
<commit_msg>handle promise exceptions<commit_after>const utils = require('../../utils')
const tsv = require('./tsv')

const validate = (
  files,
  fileList,
  tsvs,
  events,
  participants,
  phenotypeParticipants,
  stimuli,
) => {
  let issues = []
  // validate tsv
  const tsvPromises = files.map(function(file) {
    return new Promise((resolve, reject) => {
      utils.files
        .readFile(file)
        .then(contents => {
          // Push TSV to list for custom column verification after all data dictionaries have been read
          tsvs.push({
            file: file,
            contents: contents,
          })
          if (file.name.endsWith('_events.tsv')) {
            events.push({
              file: file,
              path: file.relativePath,
              contents: contents,
            })
          }
          tsv(file, contents, fileList, function(
            tsvIssues,
            participantList,
            stimFiles,
          ) {
            if (participantList) {
              if (file.name.endsWith('participants.tsv')) {
                participants = {
                  list: participantList,
                  file: file,
                }
              } else if (file.relativePath.includes('phenotype/')) {
                phenotypeParticipants.push({
                  list: participantList,
                  file: file,
                })
              }
            }
            if (stimFiles && stimFiles.length) {
              // add unique new events to the stimuli.events array
              stimuli.events = [...new Set([...stimuli.events, ...stimFiles])]
            }
            issues = issues.concat(tsvIssues)
            return resolve()
          })
        })
        .catch(reject)
    })
  })

  return new Promise((resolve, reject) =>
    Promise.all(tsvPromises)
      .then(() => resolve(issues))
      .catch(reject),
  )
}

module.exports = validate
<|endoftext|>