Skip to content

Commit

Permalink
Updated the Titanium CLI hook to subprocess the Alloy CLI if not bein…
Browse files Browse the repository at this point in the history
…g run from a well known location.
  • Loading branch information
cb1kenobi committed Oct 9, 2012
1 parent 92fa273 commit 1f11f81
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 26 deletions.
5 changes: 5 additions & 0 deletions Alloy/commands/new/index.js
Expand Up @@ -131,6 +131,7 @@ function installPlugin(paths) {
var id = 'ti.alloy';
var source = path.join(paths.alloy,'plugin',file);
var dest = path.join(paths.project,'plugins',id);
var hookDest = path.join(dest,'hooks');

// create plugin path and add to project
U.ensureDir(dest);
Expand All @@ -143,6 +144,10 @@ function installPlugin(paths) {
version: '1.0'
});

// copy the new cli hook
U.ensureDir(hookDest);
U.copyFileSync(path.join(paths.alloy,'hooks','alloy.js'), path.join(hookDest,'alloy.js'));

logger.info('Deployed ti.alloy compiler plugin to ' + dest);
}

127 changes: 102 additions & 25 deletions hooks/alloy.js
Expand Up @@ -13,32 +13,42 @@ exports.init = function (logger, config, cli, appc) {
i18n = appc.i18n(__dirname),
__ = i18n.__,
__n = i18n.__n,
pkginfo = appc.pkginfo.package(module);
pkginfo = appc.pkginfo.package(module),
exec = require('child_process').exec,
spawn = require('child_process').spawn,
parallel = appc.async.parallel;

cli.addHook('build.pre.compile', function (build, finished) {
var appDir = path.join(cli.argv['project-dir'], 'app'),
origLimit = Error.stackTraceLimit;
var appDir = path.join(cli.argv['project-dir'], 'app');
if (!afs.exists(appDir)) {
logger.info(__('Project not an Alloy app, continuing'));
finished();
return;
}

logger.info(__('Found Alloy app in %s', appDir.cyan));

Error.stackTraceLimit = Infinity;
var compilerCommand = afs.resolvePath(__dirname, '..', 'Alloy', 'commands', 'compile', 'index.js'),
config = {
platform: cli.argv.platform,
version: '0',
simtype: 'none',
devicefamily: /iphone|ios/.test(cli.argv.platform) ? build.deviceFamily : 'none',
deploytype: build.deployType || cli.argv['deploy-type'] || 'development'
};

if (afs.exists(appDir)) {
config = Object.keys(config).map(function (c) {
return c + '=' + config[c];
}).join(',');

if (afs.exists(compilerCommand)) {
// we're being invoked from the actual alloy directory!
// no need to subprocess, just require() and run
var origLimit = Error.stackTraceLimit;
Error.stackTraceLimit = Infinity;
try {
logger.info(__('Found Alloy app in %s', appDir));

var compiler = require(afs.resolvePath(__dirname, '..', 'Alloy', 'commands', 'compile', 'index.js')),
config = {
platform: cli.argv.platform,
version: '0',
simtype: 'none',
devicefamily: /iphone|ios/.test(cli.argv.platform) ? build.deviceFamily : 'none',
deploytype: build.deployType || cli.argv['deploy-type'] || 'development'
};

compiler({ /* no args */ }, {
/* program object */
config: Object.keys(config).map(function (c) {
return c + '=' + config[c];
}).join(','),
require(compilerCommand)({}, {
config: config,
outputPath: cli.argv['project-dir'],
_version: pkginfo.version,
});
Expand All @@ -48,12 +58,79 @@ exports.init = function (logger, config, cli, appc) {
line && logger.error(line);
});
}
Error.stackTraceLimit = origLimit;
finished();
} else {
logger.info(__('Project not an Alloy app, continuing'));
// we have no clue where alloy is installed, so we're going to subprocess
// alloy and hope it's in the system path or a well known place
var paths = {};
parallel(this, ['alloy', 'node'].map(function (bin) {
return function (done) {
var envName = 'ALLOY_' + (bin == 'node' ? 'NODE_' : '') + 'PATH';
if (paths[bin] = process.env[envName]) {
done();
} else if (process.platform == 'win32') {
paths['alloy'] = 'alloy.cmd';
done();
} else {
exec('which ' + bin, function (err, stdout, strerr) {
if (!err) {
paths[bin] = stdout.trim();
done();
} else {
parallel(this, [
'/usr/local/bin/' + bin,
'/opt/local/bin/' + bin,
path.join(process.env['HOME'], 'local/bin', bin),
'/opt/bin/' + bin,
'/usr/bin/' + bin
].map(function (p) {
return function (cb) {
afs.exists(p) && (paths[bin] = p);
cb();
};
}), done);
}
});
}
};
}), function () {
var cmd = [paths.node, paths.alloy, 'compile', appDir, '--config', config];
cli.argv['no-colors'] && cmd.push('--no-colors');
process.platform == 'win32' && cmd.shift();
logger.info(__('Executing Alloy compile: %s', cmd.join(' ').cyan));

var child = spawn(cmd.shift(), cmd);
// this regex is used to strip [INFO] and friends from alloy's output and re-log it using our logger
re = new RegExp('(\u001b\\[\\d+m)?\\[?(' + logger.getLevels().join('|') + ')\\]?\s*(\u001b\\[\\d+m)?(.*)', 'i');

child.stdout.on('data', function (data) {
data.toString().split('\n').forEach(function (line) {
if (line) {
var m = line.match(re);
if (m) {
logger[m[2].toLowerCase()](m[4].trim());
} else {
logger.debug(line);
}
}
});
});
child.stderr.on('data', function (data) {
data.toString().split('\n').forEach(function (line) {
line && logger.error(line);
});
});
child.on('exit', function (code) {
if (code) {
logger.error(__('Alloy compiler failed'));
} else {
logger.info(__('Alloy compiler completed successfully'));
}
finished();
});
});
}

Error.stackTraceLimit = origLimit;
finished();
});

};
4 changes: 3 additions & 1 deletion locales/en.js
@@ -1,5 +1,7 @@
{
"Project not an Alloy app, continuing": "Project not an Alloy app, continuing",
"Found Alloy app in %s": "Found Alloy app in %s",
"Alloy compiler failed": "Alloy compiler failed",
"Project not an Alloy app, continuing": "Project not an Alloy app, continuing"
"Executing Alloy compile: %s": "Executing Alloy compile: %s",
"Alloy compiler completed successfully": "Alloy compiler completed successfully"
}

0 comments on commit 1f11f81

Please sign in to comment.