ember-cli-ajh
Version:
Command line tool for developing ambitious ember.js apps
193 lines (165 loc) • 5.69 kB
JavaScript
;
var symlinkOrCopySync = require('symlink-or-copy').sync;
var path = require('path');
var fs = require('fs-extra');
var runCommand = require('./run-command');
var Promise = require('../../lib/ext/promise');
var tmp = require('./tmp');
var conf = require('./conf');
var existsSync = require('exists-sync');
var copy = Promise.denodeify(require('cpr'));
var root = process.cwd();
var exec = Promise.denodeify(require('child_process').exec);
var runCommandOptions = {
// Note: We must override the default logOnFailure logging, because we are
// not inside a test.
log: function() {
return; // no output for initial application build
}
};
function handleResult(result) {
if (result.output) { console.log(result.output.join('\n')); }
if (result.errors) { console.log(result.errors.join('\n')); }
throw result;
}
function downloaded(item) {
var exists = false;
switch (item) {
case 'node_modules':
exists = existsSync(path.join(root, '.node_modules-tmp'));
break;
case 'bower_components':
exists = existsSync(path.join(root, '.bower_components-tmp'));
break;
}
return exists;
}
function mvRm(from, to) {
var dir = path.join(root, to);
from = path.resolve(from);
if (!existsSync(dir)) {
fs.mkdirsSync(dir);
fs.copySync(from, to);
fs.removeSync(from);
}
}
function symLinkDir(projectPath, from, to) {
symlinkOrCopySync(path.resolve(root, from), path.resolve(projectPath, to));
}
function applyCommand(command, name /*, ...flags*/) {
var flags = [].slice.call(arguments, 2, arguments.length);
var args = [path.join('..', 'bin', 'ember'), command, '--disable-analytics', '--watcher=node', '--skip-git', name, runCommandOptions];
flags.forEach(function(flag) {
args.splice(2, 0, flag);
});
return runCommand.apply(undefined, args);
}
function createTmp(command) {
return tmp.setup('./common-tmp').then(function() {
process.chdir('./common-tmp');
conf.setup();
return command();
});
}
/**
* Use `createTestTargets` in the before hook to do the initial
* setup of a project. This will ensure that we limit the amount of times
* we go to the network to fetch dependencies.
* @param {String} projectName The name of the project. Can be a app or addon.
* @param {Object} options
* @property {String} options.command The command you want to run
* @return {Promise} The result of the running the command
*/
function createTestTargets(projectName, options) {
var command;
options = options || {};
options.command = options.command || 'new';
var noNodeModules = !downloaded('node_modules');
// Fresh install
if (noNodeModules && !downloaded('bower_components')) {
command = function() {
return applyCommand(options.command, projectName);
};
// bower_components but no node_modules
} else if (noNodeModules && downloaded('bower_components')) {
command = function() {
return applyCommand(options.command, projectName, '--skip-bower');
};
// node_modules but no bower_components
} else if (!downloaded('bower_components') && downloaded('node_modules')) {
command = function() {
return applyCommand(options.command, projectName, '--skip-npm');
};
} else {
// Everything is already there
command = function() {
return applyCommand(options.command, projectName, '--skip-npm', '--skip-bower');
};
}
return createTmp(function() {
return command().
catch(handleResult).
then(function(value) {
if (noNodeModules) {
return exec('npm install ember-disable-prototype-extensions').then(function() {
return value;
});
}
return value;
});
});
}
/**
* Tears down the targeted project download directory
* and restores conf.
* @return {Promise}
*/
function teardownTestTargets() {
return tmp.teardown('./common-tmp').then(function() {
conf.restore();
});
}
/**
* Creates symbolic links from the dependency temp directories
* to the project that is under test.
* @param {String} projectName The name of the project under test
* @return {Promise}
*/
function linkDependencies(projectName) {
var targetPath = './tmp/' + projectName;
return tmp.setup('./tmp').then(function() {
return copy('./common-tmp/' + projectName, targetPath);
}).then(function() {
var nodeModulesPath = targetPath + '/node_modules/';
var bowerComponentsPath = targetPath + '/bower_components/';
mvRm(nodeModulesPath, '.node_modules-tmp');
mvRm(bowerComponentsPath, '.bower_components-tmp');
if (!existsSync(nodeModulesPath)) {
symLinkDir(targetPath, '.node_modules-tmp', 'node_modules');
}
if (!existsSync(bowerComponentsPath)) {
symLinkDir(targetPath, '.bower_components-tmp', 'bower_components');
}
process.chdir('./tmp');
var appsECLIPath = path.join(projectName, 'node_modules', 'ember-cli');
var pwd = process.cwd();
fs.removeSync(projectName + '/node_modules/ember-cli');
// Need to junction on windows since we likely don't have persmission to symlink
// 3rd arg is ignored on systems other than windows
fs.symlinkSync(path.join(pwd, '..'), appsECLIPath, 'junction');
process.chdir(projectName);
});
}
/**
* Clean a test run and optionally assert.
* @return {Promise}
*/
function cleanupRun() {
return tmp.teardown('./tmp');
}
module.exports = {
createTestTargets: createTestTargets,
linkDependencies: linkDependencies,
teardownTestTargets: teardownTestTargets,
cleanupRun: cleanupRun
};